On Thu, Nov 12, 2020 at 09:57:35PM +0100, Heinrich Schuchardt wrote: > Am 12. November 2020 21:45:56 MEZ schrieb "Michael Kerrisk (man-pages)" <mtk.manpages@xxxxxxxxx>: > >On 11/12/20 5:25 PM, Heinrich Schuchardt wrote: > > > >[...] > > > >> Hello Michael, > >> > >> this text is very helpful. > >> > >> "Signal mask and pending signals" already mentions that the signal > >mask > >> controls the blocking of signals. But maybe you could reiterate this > >in > >> 1d) and in the note below 5). > > > >Yes, that perhaps does not hurt. Some light tweaks: > > > > Execution of signal handlers > > Whenever there is a transition from kernel-mode to user-mode exe‐ > > cution (e.g., on return from a system call or scheduling of a > > thread onto the CPU), the kernel checks whether there is a pending > > signal for which the process has established a signal handler. If > > there is such a pending signal, the following steps occur: > > > > 1. The kernel performs the necessary preparatory steps for execu‐ > > tion of the signal handler: > > > > a) The signal is removed from the set of pending signals. > > > > b) If the thread has defined an alternate signal stack (using > > sigaltstack(2)), then that stack is installed. > > > > c) Various pieces of signal-related context are saved into a > > "hidden" frame that is created on the stack. The saved in‐ > > formation includes: Can we delete "hidden" here? (In a sense it's actually less hidden than a typical compiler function frame, since we do provide an explicit interface for poking about in the signal frame -- you can't do that with function frames). > > > > + the program counter register (i.e., the address of the > > next instruction in the main program that should be exe‐ > > cuted when the signal handler returns); You might also want to add something like: "Architecture-specific register state required for resuming the interrupted program." > > > > + the thread's current signal mask; > > > > + the thread's alternate signal stack settings. > > > > d) The thread's signal mask is adjusted by adding the signal > > (unless the handler was established using the SA_NODEFER > > flag) as well as any additional signals specified in > > act->sa_mask when sigaction(2) was called. These signals > > are thus blocked while the handler executes. I'd delete "adjusted" since it adds nothing to the meaning. Would this also be more readable if the logic is flipped around: --8<-- Any signals specified in act->sa_mask when registering the handler are added to the thread's signal mask. The signal being delivered is also added to the signal mask, unless SA_NODEFER was specified when registering the handler. -->8-- > > > > 2. The kernel constructs a frame for the signal handler on the > > stack. Within that frame, the return address points to a piece > > of user-space code called the signal trampoline (described in > > sigreturn(2)). Not all architectures put the function return information on the stack. The kernel has to explicitly fix up the pc to run the signal handler here -- it doesn't happen by magic. So maybe say for (2): --8<-- The kernel sets the program counter for the thread to point to the first instruction of the signal handler, and configures the return address for this function to point to a piece of user-space code called the signal trampoline [...]. -->8-- > > > > 3. The kernel passes control back to user-space, where execution > > commences at the start of the signal handler function. > > > > 4. When the signal handler returns, control passes to the signal > > trampoline code. > > > > 5. The signal trampoline calls sigreturn(2), a system call that > > uses the information in the "hidden" stack frame to restore the > > thread's signal mask and alternate stack settings to their > > state before the signal handler was called. Upon completion of > > the call to sigreturn(2), the kernel transfers control back to > > user space, and the thread recommences execution at the point > > where it was interrupted by the signal handler. > > > > Note that if the signal handler does not return (e.g., control is > > transferred out of the handler using sigsetjmp(3) or swapcon‐ siglongjmp(), not sigsetjmp(). > > text(3), or the handler executes a new program with execve(2)), > > then the final step is not performed. In particular, in such sce‐ > > narios it is the programmer's responsibility to restore the state > > of the signal mask, if it is desired unblock the signals that were > > blocked on entry to the signal handler. I'm pretty sure sigsetjmp(), and probably setcontext(), _do_ restore the signal mask. [...] Cheers ---Dave