Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Is wait not interruptable?



Bart Schaefer wrote:
> } if HUP is set in a non-interactive shell you'd expect the SIGHUP to be
> } sent.
> 
> Well, yes and no.  In a non-interactive shell there is theoretically no
> controlling TTY, so there's no reason to expect to receive a HUP in the
> first place, so no reason to expect it to be sent either.

Hmm... there's may still be a process group, with the shell executing
the commands as leader, right?  Although that will depend how the script
itself was started.  Potentially, I suppose it might also kill what
started the script, if that wasn't using job control.

It seems from the original post that bash is doing something to kill its
children when it gets a signal during execution of a script, so there
seems to be some discrepancy I haven't investigated further.

I see the external command kill on Linux allows you to send a signal to
a process group, but I don't think there's a way of doing that within
zsh.

> } TRAPSASYNC was really introduced, as the name suggests, to affect trap
> } execution (see second paragraph of the section in the URL), not the
> } point at which the signal is delivered to the shell, but in practice it
> } does the former by altering the latter.  The may be a case for always
> } handling the signal immediately and altering the code only to delay any
> } traps.  But I'm still not sure why it's done the way it is.
> 
> The signals are handled the way they are mainly because of non-re-entrant
> libraries (particularly malloc) that can be confused or broken by having
> signal code executed at an arbitrary point.

But that doesn't apply here, I don't think.  The code in question is in
signal_suspend_setup().  We only execute that when the shell is about to
suspend execution to wait for a child to exit; the signal mask thus
prepared is only used during sigsuspend() or equivalent.  After the
SIGCHLD (or possibly some other signal) has been received, we then
immediately undo the signal mask (or ideally leave it to the OS when
sigsuspend() returns).  So there's no question of interrupting arbitrary
code if the signal handler is executed at that point.

Indeed, in the Linux manual entry for signal(2), sigsuspend() is listed
as a "safe function"; if a signal handler executes while the shell is
here, it's explicitly OK to call general OS stuff like malloc().  We use
dont_queue_signals() around the code that calls signal_suspend() in
waitforpid(), presumably because of this.

I wondered if it was because receiving the "wrong" signal when waiting
for SIGCHLD would confuse the shell logic.  But the loops surrounding
both calls to signal_suspend() seem to contradict that.

Surely the right thing to do would be to use a more lenient signal mask
in signal_suspend(), since we know that's a good place for signal
handling---although we might have to queue traps for later execution
unless one of TRAPSASYNC or the wait builtin is in use.

So is the delayed execution of traps the only issue?  What have I
missed?  Signal handlers theselves don't need to guard against recursive
calling, do they?

> The "wait" builtin should
> probably set TRAPS_ASYNC implicitly during its execution, based on the
> text in 2.11 at that POSIX URL you indicated.

I think you're right that the wait code (which is currently special) and
the TRAPSASYNC code should probably do the same thing.

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author