How are asynchronous signal handlers executed on Linux?

I would like to know exactly how processing asynchronous signal handlers in Linux works. Firstly, I don’t understand which thread the signal handler executes. Secondly, I would like to know the steps that are taken for the thread to execute the signal handler.

On the first question, I read two different, seemingly contradictory explanations:

  • Linux kernel, by Andries Brouwer, §5.2 Receive Signals state :

    When a signal arrives, the process is interrupted, the current registers are saved, and the signal handler is called. When the signal handler returns, the interrupted activity continues.

  • The StackOverflow question “Working with asynchronous signals in a multi-threaded program” leads me to think that Linux behaves like SCO Unix :

    When a signal is delivered to a process, if it is caught, it will be processed by one and only one of the threads that satisfy one of the following conditions:

    • The thread is blocked in the sigwait (2) system call, whose argument includes the type of signal caught.

    • A stream whose signal mask does not include the type of signal caught.

    Additional considerations:

    • In a thread blocked in sigwait (2) , preference is given to a thread that does not block the signal type.
    • If more than one thread meets these requirements (perhaps two threads call sigwait (2) ), then one of them will be selected. This choice is not predictable by application programs.
    • If the thread does not fit, the signal will remain “pending” at the process level until a thread is received.

    In addition, the “Linux Signal Processing Model” by Moshe Bar states “Asynchronous signals are delivered to the first stream that does not block the signal.”, Which I interpret as meaning that the signal is delivered to some stream that has its own sigmasc that does not include the signal .

Which one is correct?

In the second case, what happens to the stack and registers the contents for the selected stream? Suppose that the stream handler for the trigger signal is in the middle of the do_stuff() function. Is the T-stack stream used directly to execute the signal handler (i.e., the trampoline address of the signal is pushed onto the T stack, and the control flow goes to the signal handler)? Alternatively, do you use a separate stack? How it works?

+49
c linux signals signal-handling
Aug 04 2018-11-11T00:
source share
1 answer

These two explanations really do not contradict each other, given the fact that Linux hackers tend to get confused about the difference between a thread and a process, mainly due to a historical error when trying to pretend that threads can be implemented as processes that share memory .:-)

Based on the foregoing, explanation No. 2 is much more detailed, complete and correct.

Regarding the contents of the stack and the register, each thread can register its own alternative signal processing stack, and the process can select from a signal based on each signal that will be transmitted to alternating signal processing stacks. The interrupted context (registers, signal mask, etc.) will be stored in the ucontext_t structure in the (possibly alternative) stack for the stream along with the trampoline return address. Signal handlers set with the SA_SIGINFO flag can examine this ucontext_t structure if they want, but the only portable thing they can do with it is to examine (and possibly change) the stored signal mask. (I’m not sure that its change is authorized by the standard, but it is very useful because it allows the signal processor to atomically replace the interrupted code signal mask upon return, for example, to leave the signal blocked so that it does not happen again.)

+24
Aug 04 2018-11-21T00:
source share
— -



All Articles