Search code examples
cmultithreadingsignalsposixrtos

If sigwait() blocks, when is the accepted signal actually "selected"?


There are two real-time threads. The first one has low priority and it is waiting for all possible signals in sigwait() (so all signals are blocked and sigmask passed to the function has all signals enabled). The second one has high priority and sends two signals to the first (low priority) thread - it first sends SIGRTMAX and then SIGRTMIN.

POSIX spec for sigwait() ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigwait.html ) says this:

If no signal in set is pending at the time of the call, the thread shall be suspended until one or more becomes pending.

[...]

Should any of the multiple pending signals in the range SIGRTMIN to SIGRTMAX be selected, it shall be the lowest numbered one.

The sequence of events in a real-time operating system would look like that:

(H)...............signal(SIGRTMAX)===signal(SIGRTMIN)===...
(L)===sigwait().........................................===
      ^           ^                  ^                  ^
      1           2                  3                  4
  • (H) - high priority thread
  • (L) - low priority thread
  • . - thread is not running
  • = - thread is running

The 4 interesting points:

  1. low priority thread blocks on sigwait(), no signals are currently pending, all signals are blocked, high priority thread is not yet started;
  2. high priority thread starts and sends SIGRTMAX signal to low priority thread, which is unblocked, but not allowed to run, as high priority thread is still running;
  3. high priority thread continues running and sends SIGRTMIN signal to low priority thread, but low priority thread is still waiting to actually run;
  4. high priority thread terminates, low priority thread is allowed to run and return from sigwait() call;

Now the problem is that if both SIGRTMIN and SIGRTMAX signals are pending at the same time, SIGRTMIN should be "selected" first. However I'm not sure at which point the signal is actually "selected" - is it selected by the kernel at "2" or maybe it is selected by code in sigwait() executed in low priority thread, so at "4"? That's why I'm not sure whether in the scenario above, the sigwait() call would actually select SIGRTMIN or SIGRTMAX. Maybe such details are "implementation defined"?

The questions is releated to the real-time operating system for microcontrollers I'm developing ( https://github.com/DISTORTEC/distortos ). Currently my code "selects" the signal during generation, so at "2" (my code would return SIGRTMAX first), but I'm no longer sure that's the correct way to do it...


Solution

  • I'd consider the scenario described a race. So, well, the outcome is implementation defined.

    Signals should not be used for synchronisation. If the order of receiving the two signals is important (to the application) it should take the appropriate actions to synchronise (them).