Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The kernel doesn't really care that process-1 is "waiting for process-2 to finish" (in particular it's not interested in "why" it's in the state it is, merely that it <em>is</em> in some state: in this case, idling in the kernel waiting for some event). For typical<sup>1</sup> caught signals, the signal-sender essentially just sets some bit(s) in the signal-receiver's process/thread state, and then if appropriate, schedules that process/thread to run so that it can see those bits. If the receiver is idling in the kernel waiting for some event, that's one of the "schedule to run" cases. (Other common situations include: the receiver is in STOP state, where it stays stopped except for <code>SIGCONT</code> signals; or, the receiver is running in user mode, where it is set up to transition to kernel mode so as to notice the pending signals.)</p> <p>Both <code>SIGKILL</code> and <code>SIGSTOP</code> cannot be caught or ignored, so, no, you cannot provide a handler for these. (Normally processes are put into stop state via <code>SIGTSTP</code>, <code>SIGTTIN</code>, or <code>SIGTTOU</code>, all of which <em>can</em> be caught or ignored.)</p> <p>If system calls are set to restart after a user signal handler returns (via the <code>SA_RESTART</code> flag of <code>sigaction()</code>), this is achieved by setting up the "return address" for the <code>sigreturn()</code> operation to, in fact, make the system call over again. That is, if process-1 is in <code>waitpid()</code>, the sequence of operations (from process-1's point of view) from the point of the initial <code>waitpid()</code>, through receiving a caught signal <code><em>s</em></code>, and back to more waiting, is:</p> <ol> <li>system call: <code>waitpid()</code></li> <li>put self to sleep waiting for an event</li> <li>awakened: check for awakening event</li> <li>event is signal and signal is caught, so:</li> <li>set new signal mask per <code>sigaction()</code> settings (see <code>sigaction()</code>)</li> <li>push signal frame on a stack (see <code>SA_ONSTACK</code> and <code>sigaltstack()</code>)</li> <li>set up for user code (program counter) to enter at "signal trampoline"</li> <li>return to user code (into trampoline)</li> </ol> <p>(At this point process-1 is back in user mode. The remaining steps are not numbered because I can't make SO start at 9. :-) )</p> <ul> <li>call user handler routine (still on stack chosen above)</li> <li>when user routine returns, execute <code>sigreturn()</code> system call, using the frame stored at setup time, possibly modified by user routine</li> </ul> <p>(At this point the process enters kernel mode, to execute <code>sigreturn()</code> system call)</p> <ul> <li>system call: <code>sigreturn()</code>: set signal mask specified by <code>sigreturn()</code> argument</li> <li>set other registers, including stack pointer(s) and program counter, as specified by <code>sigreturn()</code> arguments</li> <li>return to user code</li> </ul> <p>(the program is now back in user mode, with registers set up to enter <code>waitpid</code>)</p> <ol> <li>system call: <code>waitpid()</code></li> </ol> <p>At this point the process returns to the same state it had before it received the caught signal: <code>waitpid</code> puts it to sleep waiting for an event (step 2). Once awakened (step 3), either the event it was waiting for has occurred (e.g., the process being <code>waitpid()</code>-ed is done) and it can return normally, or another caught signal has occurred and it should repeat this sequence, or it is being killed and it should clean up, or whatever.</p> <p>This sequence is why some system calls (such as some <code>read()</code>-like system calls) will "return early" if interrupted by a signal: they've done something irreversible between the "first" entry into the kernel and the time the signal handler is to be run. In this case, the signal frame pushed at step 6 <em>must not</em> have a program-counter value that causes the entire system call to restart. If it did, the irreversible work done before the process went to sleep would be lost. So, it is instead set up to return to the instruction that detects a successful system call, with the register values set up to return the short <code>read()</code> count, or whatever.</p> <p>When system calls are set up <em>not</em> to restart (<code>SA_RESTART</code> is not set), the signal frame pushed in step 6 is also different. Instead of returning to the instruction that executes the system call, it returns to the instruction that detects a failed system call, with the register values set up to indicate an <code>EINTR</code> error.</p> <p>(Often, but not always, these are the same instruction, e.g., a conditional branch to test for success/fail. In my original SPARC port, I made them different instructions in most cases. Since leaf routines return to <code>%o6+8</code> with no register or stack manipulation, I just set a bit indicating that a successful return should return to the leaf routine's return address. So most system calls were just "put syscall number and ret-on-success flag into <code>%g1</code>, then trap to kernel, then jump-to-error-handling because the system call must have failed if we got here.")</p> <hr> <p><sup>1</sup>Versus <a href="http://linux.die.net/man/2/rt_sigqueueinfo" rel="nofollow">queued signals</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload