| --- a/nih/signal.c |
| +++ b/nih/signal.c |
| @@ -337,17 +337,37 @@ |
| |
| nih_signal_init (); |
| |
| + /* Since this poller runs w/out signals masked, we do not want to try |
| + * and clear any other signals (like zeroing the caught array at the |
| + * end). If we do that, we open a race: |
| + * - Walk the list of signals. |
| + * - First one is not set so we move on to the second one. |
| + * - First signal comes in while processing second and increments the |
| + * caught array entry. |
| + * - Finish walking the whole list. |
| + * - Zero out the whole list and thus throw away the first signal. |
| + * Since the signal handlers can take any length of time, this race |
| + * can be open for a variable amount of time. |
| + */ |
| + |
| NIH_LIST_FOREACH_SAFE (nih_signals, iter) { |
| NihSignal *signal = (NihSignal *)iter; |
| |
| if (! signals_caught[signal->signum]) |
| continue; |
| |
| + /* Now that we know we're going to process this signal, clear |
| + * out all pending counts for it. There is a slight race here |
| + * where the same signal can come in, but the API has never |
| + * guaranteed exact coverage since POSIX does not provide it -- |
| + * more than one signal can be collapsed into one event. All |
| + * we can guarantee is that we'll notice signals that come in |
| + * once the handler runs. |
| + */ |
| + signals_caught[signal->signum] = 0; |
| + |
| signal->handler (signal->data, signal); |
| } |
| - |
| - for (s = 0; s < NUM_SIGNALS; s++) |
| - signals_caught[s] = 0; |
| } |
| |
| |
| |