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

Re: A tail of two situations

On Saturday, May 11, 2013, Jeremy Mates wrote:
> This seems inconsistent, as the behavior deep within ZSH (with MONITOR
> set) depends on how(if) the program handles the ^C. Consistency in ZSH
> demands either `unsetopt MONITOR` (subsequent code never run), or using
> a subshell and trapping INT via a "function trap"

Although this may seem inconsistent, the definition of signal delivery in
Unix-like operating systems makes it difficult to do anything else.  A
signal may be delivered either to a single process, or to all processes in
a single process group.  As explained in the comment you quoted:

>     /* When MONITOR is set, the foreground process runs in a different *
>      * process group from the shell, so the shell will not receive     *
>      * terminal signals, therefore we pretend that the shell got       *
>      * the signal too.                                                 */

For process groups, you can think of it as if the signal were percolating
toward the root of the process tree from the leaf children.  If the
"leader" (closest to the root) of the signalled process group handles the
signal, then that's the end of it; the only way its parent can determine
what happened is by examining the exit status, which the child can set to
anything it likes.  (In your example there is only one process in the
group, so the leaf is the leader.)

For comparison, consider what you'd want to have happen if "tail" handled
the signal and then proceeded without exiting, until it eventually exited
with status zero somewhere down the line.

To be "consistent" zsh could, when monitor is off, discard the signal that
it recieves as the group leader and always run the next command, thus
"pretending" that every foreground process is its own group leader; but
that leads to things like shell scripts it is impossible to interrupt.
 (It's true there are other things that also lead to that, but they are
less common.)

The other option, when monitor is on, would be to create an extra zsh
process whose sole job is to be the leader of every foreground process
group, to be certain of receiving all signals and alerting the parent
shell.  This means doubling the number of forks on every command and having
an otherwise useless extra copy of the shell hanging around, even though *most*
processes are well-behaved and reveal the signal state in their exit status.

In fact the reason you need the trap in the subshell is because zsh instead
chooses to minimize the number of forks or extra copies of itself, and so
exec's the subshell out of existence if it has no traps and only a single
child to wait for.

Originally (before the writing of the code that goes along with the comment
you quoted), zsh "consistently" ignored whether the exit status indicated a
signal and only responded to signals that it received directly.  Users
complained that this did not match expectation in the "well-behaved child"
situation, and here we are.

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