Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] problem with 'ls | less' shell function
> 2022/11/04 15:09, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> Unfortunately, that leaves us with another example in 50105 still unfixed:
>
> ( zsh -fc 'print a few words; /bin/sleep 10' ) | { head -n 1 }
The main zsh (zsh0, pid=pgid=100) forks two times;
the 1st one exec 'zsh -fc' (zsh1, pid=101), the 2nd one 'head' (pid=102).
Both are in the process group pgid=101, and the group becomes foreground.
But it seems these two are in different jobs (because of { head } ?).
Then zsh1 exec 'sleep 100' (without forking). Now 'sleep 100' has pid=101
and pgid=101.
When 'head' exits, zsh0 calls update_job(). In this function:
548 /* is this job in the foreground of an interactive shell? */
549 if (mypgrp != pgrp && inforeground &&
550 (jn->gleader == pgrp ||
551 (pgrp > 1 &&
552 (kill(-pgrp, 0) == -1 && errno == ESRCH)))) {
mypgrp=100, pgrp=101, jn->gleader=101, and the if(...) holds, and the line
568 jn->stat |= STAT_ATTACH;
is executed. Since { head } is a separate job and head has exited, the
job will be removed, and attachtty(mypgrp=100) will be called when the
job is removed. Then pgid=101 (=sleep 100) lose tty.
But why just "jn->gleader == pgrp" is enough to assume that the foreground
job has finished? If the line 550 above is replaced by
550 (
then ^C works for
[1] ( zsh -fc 'print a few words; /bin/sleep 10' ) | { head -n 1 }
But now we need two ^C's to kill
[2] { sleep 10; sleep 20; } | { sleep 30; sleep 40; }
Another code that looks suspicious to me is (also in jobs.c)
478 if (pn->pid == jn->gleader) /* if this process is process group leader */
479 status = pn->status;
480 }
The 'status' is later used at (line numbers after the patch pipejobs.txt):
641 if (inforeground == 2 && isset(MONITOR) && WIFSIGNALED(status)) {
When 'sleep 30' is killed, pn->pid=(pid of sleep 30), but it is not equal
to jn->gleader (= probably 'sleep 10'?). Then if() at line 641 does not hold,
and 'sleep 40' will be started.
If the line 478 is replaced by
478 if (WIFSIGNALED(pn->status) || pn->pid == jn->gleader)
then [2] can be killed by a single ^C. But I guess it will have bad side
effects. And ^Z/fg (still) does not work for [2].
Sorry, I have no time now to investigate further.
Messages sorted by:
Reverse Date,
Date,
Thread,
Author