1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-07-15 18:11:25 +02:00

50874: fix handling of tty signals for jobs in the current shell when waiting for the right side of a pipeline.

Reverts 15bf8ace (workers/50134).  Thanks to Jun T. for debugging assistance.

Issues came down to two things:
1. update_job() may be called on a process group leader even when a
   signal was NOT sent to any process in that process group.  This
   caused jobs to be resumed or backgrounded incorrectly or in the
   wrong order.
2. When there is a current-shell complex command (in braces) on the
   right side of a pipeline, external processes within it have their
   own process groups, but a tty signal sent to such a process should
   be treated as if received by the whole complex command.

This fixes:
* Suspend/resume of a foreground pipeline within a shell function
* Interrupt or suspend/resume of processes in a pipeline ending in { ... }
* Interrupt of such a pipeline after exit of the last process in { ... }

These affected interactive shells only (MONITOR set plus tty signals).
This commit is contained in:
Bart Schaefer 2022-11-06 11:25:47 -08:00
parent f8d93888a8
commit 188c5cd518
2 changed files with 18 additions and 11 deletions

View file

@ -1,3 +1,8 @@
2022-11-06 Bart Schaefer <schaefer@zsh.org>
* 50874: Src/jobs.c: fix handling of tty signals for jobs in
the current shell when waiting for the right side of a pipeline.
2022-11-02 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
* 50851: Doc/Zsh/options.yo, Src/exec.c, Src/options.c: restore

View file

@ -544,16 +544,14 @@ update_job(Job jn)
if (isset(MONITOR)) {
pid_t pgrp = gettygrp(); /* get process group of tty */
int deadpgrp = (mypgrp != pgrp && inforeground && pgrp > 1 &&
kill(-pgrp, 0) == -1 && errno == ESRCH);
/* is this job in the foreground of an interactive shell? */
if (mypgrp != pgrp && inforeground &&
(jn->gleader == pgrp ||
(pgrp > 1 &&
(kill(-pgrp, 0) == -1 && errno == ESRCH)))) {
((jn->gleader == pgrp && signalled) || deadpgrp)) {
if (list_pipe) {
if (somestopped || (pgrp > 1 &&
kill(-pgrp, 0) == -1 &&
errno == ESRCH)) {
if (somestopped || deadpgrp) {
attachtty(mypgrp);
/* check window size and adjust if necessary */
adjustwinsize(0);
@ -566,6 +564,12 @@ update_job(Job jn)
* when the job is finally deleted.
*/
jn->stat |= STAT_ATTACH;
/*
* If we're in shell jobs on the right side of a pipeline
* we should treat it like a job in the current shell.
*/
if (inforeground == 2)
inforeground = 1;
}
/* If we have `foo|while true; (( x++ )); done', and hit
* ^C, we have to stop the loop, too. */
@ -1488,10 +1492,7 @@ addproc(pid_t pid, char *text, int aux, struct timeval *bgtime,
* set it for that, too.
*/
if (gleader != -1) {
if (jobtab[thisjob].stat & STAT_CURSH)
jobtab[thisjob].gleader = gleader;
else
jobtab[thisjob].gleader = pid;
jobtab[thisjob].gleader = gleader;
if (list_pipe_job_used != -1)
jobtab[list_pipe_job_used].gleader = gleader;
/*
@ -1500,7 +1501,7 @@ addproc(pid_t pid, char *text, int aux, struct timeval *bgtime,
*/
last_attached_pgrp = gleader;
} else if (!jobtab[thisjob].gleader)
jobtab[thisjob].gleader = pid;
jobtab[thisjob].gleader = pid;
/* attach this process to end of process list of current job */
pnlist = &jobtab[thisjob].procs;
}
@ -2506,6 +2507,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
jobtab[job].stat &= ~STAT_CURSH;
}
if ((stopped = (jobtab[job].stat & STAT_STOPPED))) {
/* WIFCONTINUED will makerunning() again at killjb() */
makerunning(jobtab + job);
if (func == BIN_BG) {
/* Set $! to indicate this was backgrounded */