+static volatile int sigaction_nodefer_works = -1;
+
+#define SA_NODEFER_TEST_BLOCK_SIGNAL SIGABRT
+#define SA_NODEFER_TEST_KILL_SIGNAL SIGUSR1
+
+static void
+sigaction_nodefer_test_handler(int signal, siginfo_t *info, void *void_context)
+{
+ sigset_t empty, current;
+ int i;
+ sigemptyset(&empty);
+ sigprocmask(SIG_BLOCK, &empty, ¤t);
+ /* There should be exactly two blocked signals: the two we added
+ * to sa_mask when setting up the handler. NetBSD doesn't block
+ * the signal we're handling when SA_NODEFER is set; Linux before
+ * 2.6.13 or so also doesn't block the other signal when
+ * SA_NODEFER is set. */
+ for(i = 1; i < NSIG; i++)
+ if (sigismember(¤t, i) !=
+ (((i == SA_NODEFER_TEST_BLOCK_SIGNAL) || (i == signal)) ? 1 : 0)) {
+ FSHOW_SIGNAL((stderr, "SA_NODEFER doesn't work, signal %d\n", i));
+ sigaction_nodefer_works = 0;
+ }
+ if (sigaction_nodefer_works == -1)
+ sigaction_nodefer_works = 1;
+}
+
+static void
+see_if_sigaction_nodefer_works()
+{
+ struct sigaction sa, old_sa;
+
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sa.sa_sigaction = sigaction_nodefer_test_handler;
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SA_NODEFER_TEST_BLOCK_SIGNAL);
+ sigaddset(&sa.sa_mask, SA_NODEFER_TEST_KILL_SIGNAL);
+ sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &sa, &old_sa);
+ /* Make sure no signals are blocked. */
+ {
+ sigset_t empty;
+ sigemptyset(&empty);
+ sigprocmask(SIG_SETMASK, &empty, 0);
+ }
+ kill(getpid(), SA_NODEFER_TEST_KILL_SIGNAL);
+ while (sigaction_nodefer_works == -1);
+ sigaction(SA_NODEFER_TEST_KILL_SIGNAL, &old_sa, NULL);
+}
+
+#undef SA_NODEFER_TEST_BLOCK_SIGNAL
+#undef SA_NODEFER_TEST_KILL_SIGNAL
+
+static void