Chris Wellons posted a good review of why large chunks of the C
library are terrible,
especially if you are coding on Windows - good fun if you like staring
into the abyss. He followed up with let’s write a
setjmp which is fun in a
more positive way. I was also pleased to learn about
__builtin_longjmp
! There’s a small aside in this article about the
signal mask, which skates past another horrible abyss - which might
even make it sensible to DIY longjmp
.
Some of the nastiness can be seen in the POSIX rationale for
sigsetjmp
which says that on BSD-like systems, setjmp
and
_setjmp
correspond to sigsetjmp
and setjmp
on System V Unixes.
The effect is that setjmp
might or might not involve a system call
to adjust the signal mask. The syscall overhead might be OK for
exceptional error recovery, such as Chris’s arena out of memory
example, but it’s likely to be more troublesome if you are
implementing coroutines.
But why would they need to mess with the signal mask? Well, if you are
using BSD-style signals or you are using sigaction
correctly, a
signal handler will run with its signal masked. If you decide to
longjmp
out of the handler, you also need to take care to unmask the
signal. On BSD-like systems, longjmp
does that for you.
The problem is that longjmp
out of a signal handler is basically
impossible to do correctly. (There’s a whole flamewar in the wg14
committee documents on this subject.) So this is another example of
libc being optimized for the unusual, broken case at the cost of the
typical case.