So, this turned out to be much more complicated than I initially expected.
The current linux-user signal-handling implementation makes the assumption that there is a 1:1 correspondence between host signals, and target (guest) signals in a whole bunch of places. Breaking this assumption breaks a lot of the signal handling code. I’m no longer sure that “multiplexing” is a good solution. Here are some of the issues I’ve run into while implementing this patch:
* Signal masks no longer work. The existing signal handling routines assume that target masks can be translated into equivalent host masks, but if multiple target signals map to a single host signal, the masks are no longer equivalent. This can be addressed by maintaining a separate emulated target signal mask (which is checked in process_pending_signals). Note: this is largely addressed by Milos/Aleksandar's patch.
* sigaction no longer works. Right now, even though SIGRTMIN is mapped to SIGRTMAX, we are still allowed to do a “sigaction” on the signal. Without a 1:1 mapping, the action table must be fully emulated.
* Syscall interruption (SA_RESTART and EINTR) breaks. Emulating the signal action table means that QEMU must now implement SA_RESTART behavior (we can’t rely on the kernel to do this), which will require changes to most syscalls.
* sigsuspend breaks. To avoid masking too many signals with a sigsuspend, the host mask used for “sigsuspend” cannot block the multiplexing signal. This means that the sigsuspend handler may get interrupted by a multiplexed signal that is supposed to be masked by the target. Linux user-mode will have to support signal queueing to track pending RT signals.
* signalfd breaks. If the user includes a multiplexed signal in the “signalfd” set, then signalfd behavior will have to be fully emulated. The only way I can think to support this is by either completely emulating FDs, or by using something like “eventfd” or “memfd” to make a fake signalfd (that still works with select), and then injecting siginfo structures when the fake FD is read. Not pretty.
* sigtimedwait breaks. The given (target) sigset will not have an equivalent host sigset if some target signals are multiplexed. The host sigset will either be too large (possibly receiving some signals that should remain pending), or too small (missing signals that fulfil the target’s criteria, which is unacceptable). This can be worked-around by re-queuing signals and using -TARGET_ERESTARTSYS, but it’s quite complicated to make this appear atomic.
These are just the things I have found so far. I’m not sure if this is everything that is required to add actual signal multiplexing support.
If QEMU follows through with signal multiplexing, it will be a big change to QEMU signal handling. Full emulation of these signal aspects will bring QEMU further away from kernel behavior, and introduce the possibility of bugs or incompatibilities in QEMU’s signal-handling layer. To support signals outside the host range, this is unavoidable; but for the SIGRTMIN, SIGRTMIN+1 case, I’m not sure it’s worth it.
After considering these drawbacks, do the QEMU maintainers still think this is the right approach for handling these libc reserved signals?