There are two distinct groups of signals.
-@subsection Semi-synchronous signals
+@subsection Synchronous signals
-The first group, tentatively named ``semi-synchronous'', consists of
-signals that are raised on illegal instruction, hitting a protected
-page, or on a trap. Examples from this group are:
+This group consists of signals that are raised on illegal instruction,
+hitting a protected page, or on a trap. Examples from this group are:
@code{SIGBUS}/@code{SIGSEGV}, @code{SIGTRAP}, @code{SIGILL} and
@code{SIGEMT}. The exact meaning and function of these signals varies
by platform and OS. Understandably, because these signals are raised
in a controllable manner they are never blocked or deferred.
-@subsection Blockable signals
+@subsection Asynchronous or blockable signals
The other group is of blockable signals. Typically, signal handlers
block them to protect against being interrupted at all. For example
atomic section the pseudo-atomic-interrupted flag is set, the signal
and its context are stored, and all deferrable signals blocked. This
is to guarantee that there is at most one pending handler in
-SBCL. While the signals are blocked, the responsibilty of keeping
+SBCL. While the signals are blocked, the responsibility of keeping
track of other pending signals lies with the OS.
On leaving the pseudo atomic section, the pending handler is run and
deferrable by @code{WITHOUT-INTERRUPTS} is @code{SIG_STOP_FOR_GC}. It
is deferred by pseudo atomic and @code{WITHOUT-GCING}.
+@subsection When are signals handled?
+
+At once or as soon as the mechanism that deferred them allows.
+
+First, if something is deferred by pseudo atomic then it is run at the
+end of pseudo atomic without exceptions. Even when both a GC request
+or a @code{SIG_STOP_FOR_GC} and a deferrable signal such as
+SIG_INTERRUPT_THREAD interrupts the pseudo atomic section.
+
+Second, an interrupt deferred by WITHOUT-INTERRUPTS is run when the
+interrupts are enabled again. GC cannot interfere.
+
+Third, if GC or @code{SIG_STOP_FOR_GC} is deferred by
+@code{WITHOUT-GCING} then the GC or stopping for GC will happen when
+GC is not inhibited anymore. Interrupts cannot delay a gc.
+
@node Implementation warts
@section Implementation warts
the middle of an interrupted POSIX call.
For some signals this appears to be a non-issue: @code{SIGSEGV} and
-other semi-synchronous signals are raised by our code for our code,
-and so we can be sure that we are not interrupting a POSIX call with
-any of them.
+other synchronous signals are raised by our code for our code, and so
+we can be sure that we are not interrupting a POSIX call with any of
+them.
For asynchronous signals like @code{SIGALARM} and @code{SIGINT} this
is a real issue.
@code{INTERRUPT-THREAD} have the same restrictions and considerations
as signal handlers.
-Destructive modification, and holding mutexes to protect desctructive
+Destructive modification, and holding mutexes to protect destructive
modifications from interfering with each other are often the cause of
non-reentrancy. Recursive locks are not likely to help, and while
@code{WITHOUT-INTERRUPTS} is, it is considered untrendy to litter the
enable @code{QSHOW} and @code{QSHOW_SIGNALS} in runtime.h and once
SBCL runs into problems attach gdb. A simple @code{thread apply all
ba} is already tremendously useful. Another possibility is to send a
-SIGABORT to SBCL to provoke landing in LDB, if it's compiled with it
+SIGABRT to SBCL to provoke landing in LDB, if it's compiled with it
and it has not yet done so on its own.
Note, that fprintf used by QSHOW is not reentrant and at least on x86