blob: 364af7f5383e51224e06248913afe4a844784c8c [file] [log] [blame]
--- 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;
}