summaryrefslogtreecommitdiffstats
path: root/Src/exec.c
diff options
context:
space:
mode:
authorPeter Stephenson <p.stephenson@samsung.com>2018-04-13 12:09:34 +0100
committerPeter Stephenson <p.stephenson@samsung.com>2018-04-17 17:14:20 +0100
commit3c74891fcd68d37c1629943f703ac70428e3ce9f (patch)
treeb6da0e207af9a39e94e6e809690c5ea16b14b08c /Src/exec.c
parentunposted: update version to 5.5.1-dev-0 (diff)
downloadzsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar.gz
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar.bz2
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar.lz
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar.xz
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.tar.zst
zsh-3c74891fcd68d37c1629943f703ac70428e3ce9f.zip
42630: Improve process group handling in pipelines.
If process group leader exits, allow a newly forked process to become process leader. If a foreground job, reattach the shell to the terminal until that happens. Unblock signals when reading output for command subsitution so that we can do this reattaching immediately.
Diffstat (limited to 'Src/exec.c')
-rw-r--r--Src/exec.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/Src/exec.c b/Src/exec.c
index 216057aa7..f6c768f37 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4576,10 +4576,20 @@ readoutput(int in, int qt, int *readerror)
char *buf, *ptr;
int bsiz, c, cnt = 0;
FILE *fin;
+ int q = queue_signal_level();
fin = fdopen(in, "r");
ret = newlinklist();
ptr = buf = (char *) hcalloc(bsiz = 64);
+ /*
+ * We need to be sensitive to SIGCHLD else we can be
+ * stuck forever with important processes unreaped.
+ * The case that triggered this was where the exiting
+ * process is group leader of the foreground process and we need
+ * to reclaim the terminal else ^C doesn't work.
+ */
+ dont_queue_signals();
+ child_unblock();
while ((c = fgetc(fin)) != EOF || errno == EINTR) {
if (c == EOF) {
errno = 0;
@@ -4592,13 +4602,18 @@ readoutput(int in, int qt, int *readerror)
cnt++;
}
if (++cnt >= bsiz) {
- char *pp = (char *) hcalloc(bsiz *= 2);
+ char *pp;
+ queue_signals();
+ pp = (char *) hcalloc(bsiz *= 2);
+ dont_queue_signals();
memcpy(pp, buf, cnt - 1);
ptr = (buf = pp) + cnt - 1;
}
*ptr++ = c;
}
+ child_block();
+ restore_queue_signals(q);
if (readerror)
*readerror = ferror(fin) ? errno : 0;
fclose(fin);