summaryrefslogtreecommitdiff
path: root/usr/src/cmd/csh/sh.proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/csh/sh.proc.c')
-rw-r--r--usr/src/cmd/csh/sh.proc.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/usr/src/cmd/csh/sh.proc.c b/usr/src/cmd/csh/sh.proc.c
index 195d2b07a1..2e4bfc4ea9 100644
--- a/usr/src/cmd/csh/sh.proc.c
+++ b/usr/src/cmd/csh/sh.proc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -230,7 +230,29 @@ pjwait(pp)
while ((fp = (fp->p_friends)) != pp);
if ((jobflags & PRUNNING) == 0)
break;
- sigpause(sigblock(0) &~ sigmask(SIGCHLD));
+ /*
+ * At this point, csh used to call:
+ * sigpause(sigblock(0) &~ sigmask(SIGCHLD));
+ * expecting to receive a SIGCHLD signal from the
+ * termination of the child and to invoke the
+ * signal handler, pchild(), as a result.
+ *
+ * However, vfork() now causes a vfork()'d child to
+ * have all of its active signal handlers reset to
+ * SIG_DFL, to forstall parent memory corruption due
+ * to race conditions with signal handling.
+ *
+ * If this instance of csh is itself a child of vfork(),
+ * which can happen when the top-level csh performs a
+ * command substitution inside an i/o redirection, like:
+ * /bin/echo foo >`/bin/echo trash`
+ * then we will never receive SIGCHLD. To accommodate
+ * this, we wait until one of our children terminates
+ * (without actually reaping the child) and call the
+ * SIGCHLD signal handler (pchild()) directly.
+ */
+ if (csh_wait_noreap() > 0)
+ pchild(); /* simulate receipt of SIGCHLD */
}
(void) sigsetmask(omask);
if (tpgrp > 0) /* get tty back */