signals: a blocked signal stays pending instead of killing
sigsend() ended a process for a default-fatal signal (SIGUSR1, SIGTERM, SIGINT...) on arrival, whatever its signal mask said. Blocking is exactly the promise that it will not: the signal waits until it is unblocked, or until the program takes it some other way -- which is what signalfd is, and how this was found. A blocked signal is now only made pending. If it is later unblocked while still pending, deliver_signals() applies the default action then. SIGKILL cannot be blocked, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
5ed8f1b0d5
commit
6bfb367090
3 changed files with 40 additions and 12 deletions
|
|
@ -191,8 +191,17 @@ deliver_signals(struct trapframe *tf)
|
|||
// applied by sigsend(); all that is left here is to stop it being
|
||||
// pending, which the old `continue` never did, so an ignored signal
|
||||
// was re-examined on the way out of every syscall forever after.
|
||||
//
|
||||
// Except for a signal that was blocked when it arrived: sigsend()
|
||||
// left it pending without acting, and now that it is deliverable its
|
||||
// default action happens here.
|
||||
if (myproc()->sig_handler[sig] <= 1) {
|
||||
myproc()->pending_signals &= ~(1ULL << sig);
|
||||
if (myproc()->sig_handler[sig] == 0 && sig_default_kills(sig)) {
|
||||
myproc()->killed = 1;
|
||||
if (myproc()->killsig == 0)
|
||||
myproc()->killsig = sig;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue