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

Re: Bug with traps and exit

On Sat, 2019-12-14 at 11:28 +0000, Daniel Shahaf wrote:
> Peter Stephenson wrote on Fri, Dec 13, 2019 at 14:49:40 +0000:
> > As you know, getting anyone interested in looking at things is very
> > difficult.  I'm taking more of a back seat myself, unless I can see
> > something glaring.  Anyone is more than welcome to jump in while
> > the old guard is still looking on to help.
> I don't know about others, but I'm not even sure where to begin fixing this.
> I can find the code handling traps easily enough ('intrap', etc), and I know
> where the code handling functions is (doshfunc()), but how to proceed?  Would
> the right fix be to add some code in the end of runshfunc(), after
> unqueue_signals(), that checks whether a trap has been executed and called
> 'exit'…?

OK, so this is deliberately somewhat wordier than if I was just replying
to the message myself, to try to get my thinking across.  So please bear
with me.

Frankly, I'm never sure where to begin fixing *anything* that's not
immediately obvious.  The first step in something like this is to
identify key points where things need to happen and may or may not
actually be happening, and then work out whether we're hitting those
points, and if not, why not, and if so, why it's doing something
different there from what it should (which may include setting something
up differently for a future action, in this case on signal delivery).

> trap 'echo SIGINT; trap - INT; kill -s INT $$; echo woops' INT
> kill -s INT $$
> zsh prints 'woops', but shouldn't.

Martijn is presumably saying the trap - INT within the trap should reset
it so the interrupt stops the rest of the trap being dlievered.  So does
it reset it?  Actually, there's some important information below so you
probably don't need to, but what you'd have to do is trace through to
see what's happening on the "trap - INT" on the trap by getting the
shell to stop when it executes the trap command in the signal caught by
the kill.  The trap is set by the bin_trap() handler; zhandler() is
called if the shell is handling an interrupt, though not if the
interrupt is set up to kill or suspend the shell or whatever.

One easy and obvious thing to try is to simplify:

trap - INT; kill -S INT $$; echo foo

That doesn't echo "foo"; that's because the INT is delivered
immedately.  The shell doesn't exit if it's interactive, but we do get
returned immediately to the command line.

In fact, to shortcut the investigation, I think the key point here is to
note that the trap is executed inside the signal handler (see the other
recent thread on signal handlers).  So we'd expect the "kill -s INT"
inside the trap to be delivered after the first trap has exited.  So
that's probably why you get "whoops".  So is that really a problem?
You'll have to disucss that with Martijn.  Obviously that's not going to
change fundamentally without a complete rewrite, and this looks to me a
rather silly experiment anywawy --- it looks to me like it's abusing the
mechanism to reissue a signal within something designed to handle the
signal and then expect that to do something within that same handler ---
but I don't want to have to go on deciding all this by myself, so feel
free to disagree and discuss further.


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