That is not accurate. If I have a single-threaded program sitting around a ppoll(2) loop and a signal can arrive only inside my main loop ppoll(), then I know a priori that my signal handler can't be interrupting non-reentrant code and so I can call whatever I want inside it.
> It used to be even more sensitive, in that not all register state was correctly saved/restored on Linux.
Don't confuse architectural flaws with implementation bugs. I'm reminded of an argument on emacs-devel in which someone argued that we couldn't call malloc(3) in a multi-threaded program because one beta version of glibc once had a thread safety bug in the malloc implementation.
> SIGBUS is a POSIX-way to deal with mmap truncation, but sealed memfds can be used to avoid the issue altogether.
Sealing a file descriptor doesn't physically seal a USB key into a USB port. :-) You also get SIGBUS on IO failures on mmaped files, and surprise removal is an IO failure. There's really no alternative to a synchronous signal here --- a regular file being mmap()ed isn't a userfaultfd.
IMHO, I think it's crying shame that Hotspot (last time I checked --- maybe it's fixed?) doesn't watch for SIGBUS on access to MappedByteBuffer and translate surprise USB device file removal into a nice clear VM-level exception.
Even for cases for which userfaultfd can work, a synchronous signal can be more efficient because it involves just one entry into the kernel. (sigreturn is optional.) I'd really hate to give up the conventional signal mechanism entirely, although of course I approve of things like signalfd and userfault that reduce the need for signal handling.