int i;
sigemptyset(&empty);
thread_sigmask(SIG_BLOCK, &empty, ¤t);
- for(i=0;i<NSIG;i++) {
+ for(i = 1; i < NSIG; i++) {
if (sigismember(&blockable_sigset, i) && !sigismember(¤t, i))
lose("blockable signal %d not blocked",i);
}
void block_blockable_signals(void)
{
- sigset_t block;
- sigcopyset(&block, &blockable_sigset);
- thread_sigmask(SIG_BLOCK, &block, 0);
+ thread_sigmask(SIG_BLOCK, &blockable_sigset, 0);
}
\f
#ifdef LISP_FEATURE_SB_THREAD
{
sigset_t unblock;
+ sigemptyset(&unblock);
sigaddset(&unblock, SIG_STOP_FOR_GC);
thread_sigmask(SIG_UNBLOCK, &unblock, 0);
}
#ifdef LISP_FEATURE_SB_THREAD
else {
sigset_t new;
+ sigemptyset(&new);
sigaddset(&new,SIG_STOP_FOR_GC);
thread_sigmask(SIG_UNBLOCK,&new,0);
}
return 1;
}
+#ifndef LISP_FEATURE_SIGACTION_NODEFER_WORKS
+
+/* In Linux 2.4 synchronous signals (sigtrap & co) can be delivered if
+ * they are blocked, in Linux 2.6 the default handler is invoked
+ * instead that usually coredumps. One might hastily think that adding
+ * SA_NODEFER helps, but until ~2.6.13 if SA_NODEFER is specified then
+ * the whole sa_mask is ignored and instead of not adding the signal
+ * in question to the mask. That means if it's not blockable the
+ * signal must be unblocked at the beginning of signal handlers.
+ */
+void
+unblock_me_trampoline(int signal, siginfo_t *info, void *void_context)
+{
+ sigset_t unblock;
+ sigemptyset(&unblock);
+ sigaddset(&unblock, signal);
+ thread_sigmask(SIG_UNBLOCK, &unblock, 0);
+ (*interrupt_low_level_handlers[signal])(signal, info, void_context);
+}
+
+#endif
+
\f
/*
* noise to install handlers
if (sigismember(&deferrable_sigset,signal))
sa.sa_sigaction = low_level_maybe_now_maybe_later;
+#ifndef LISP_FEATURE_SIGACTION_NODEFER_WORKS
+ else if (!sigismember(&blockable_sigset, signal))
+ sa.sa_sigaction = unblock_me_trampoline;
+#endif
else
sa.sa_sigaction = handler;
sigcopyset(&sa.sa_mask, &blockable_sigset);
- sa.sa_flags = SA_SIGINFO | SA_RESTART;
+ sa.sa_flags = SA_SIGINFO | SA_RESTART
+#ifdef LISP_FEATURE_SIGACTION_NODEFER_WORKS
+ | SA_NODEFER
+#endif
+ ;
#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK
if((signal==SIG_MEMORY_FAULT)
#ifdef SIG_INTERRUPT_THREAD
}
sigcopyset(&sa.sa_mask, &blockable_sigset);
- sa.sa_flags = SA_SIGINFO | SA_RESTART;
+ sa.sa_flags = SA_SIGINFO | SA_RESTART
+#ifdef LISP_FEATURE_SIGACTION_NODEFER_WORKS
+ | SA_NODEFER
+#endif
+ ;
sigaction(signal, &sa, NULL);
}
--- /dev/null
+/*
+ * See if SA_NODEFER makes sigaction ignore sa_mask
+ * altogether. According to POSIX SA_NODEFER means: 'don't add the
+ * handler's signal to the mask'.
+ */
+
+/*
+ * This software is part of the SBCL system. See the README file for
+ * more information.
+ *
+ * While most of SBCL is derived from the CMU CL system, many
+ * utilities for the build process (like this one) were written from
+ * scratch after the fork from CMU CL.
+ *
+ * This software is in the public domain and is provided with
+ * absolutely no warranty. See the COPYING and CREDITS files for
+ * more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+void
+handler(int signal, siginfo_t *info, void *void_context)
+{
+ sigset_t empty, current;
+ int i;
+ sigemptyset(&empty);
+ sigprocmask(SIG_BLOCK, &empty, ¤t);
+ for(i = 1; i < NSIG; i++)
+ if (sigismember(¤t, i) != ((i == SIGABRT) ? 1 : 0))
+ exit(128 + i);
+ exit(104);
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct sigaction sa;
+
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sa.sa_sigaction = handler;
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGABRT);
+ sigaction(SIGTRAP, &sa, NULL);
+ kill(getpid(), SIGTRAP);
+ while (1) sleep(1);
+}