12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- https://bugs.launchpad.net/libnih/+bug/518921
- fix race in signal processing leading to lost signals
- The current loop will walk all signals one by one and run the handler
- for it if any signals were pending. Then it clears the array. But if
- a signal comes in for an earlier checked signal, it will get clobbered
- when the final clear runs.
- Change the logic so that we only clear entries for signals whose handler
- we explicitly call. If a different signal comes in, we'll process it
- the next time around.
- This was discovered & triaged by Jeffy Chen from Rockchip.
- === modified file 'nih/signal.c'
- --- nih/signal.c 2009-06-23 09:29:37 +0000
- +++ nih/signal.c 2015-05-21 08:12:11 +0000
- @@ -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;
- }
-
-
|