Use fork() rather than vfork() when forking to run a background

process with redirects.   If we use vfork() and a redirect hangs
(eg: opening a fifo) which the parent was intended to unhang,
then the parent never gets to continue to unhang the child.

eg:  mkfifo f; cat <f &; echo foo>f

The parent should not be waiting for a background process, even
just for its exec() to complete.   if there are no redirects there
is (should be) nothing left that might be done that will cause any
noticeable delay, so vfork() should be safe in all other cases.
This commit is contained in:
kre 2019-12-21 18:54:15 +00:00
parent 5056cf4d85
commit a6dacc2280
1 changed files with 5 additions and 4 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: eval.c,v 1.176 2019/12/09 00:14:24 kre Exp $ */
/* $NetBSD: eval.c,v 1.177 2019/12/21 18:54:15 kre Exp $ */
/*-
* Copyright (c) 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#else
__RCSID("$NetBSD: eval.c,v 1.176 2019/12/09 00:14:24 kre Exp $");
__RCSID("$NetBSD: eval.c,v 1.177 2019/12/21 18:54:15 kre Exp $");
#endif
#endif /* not lint */
@ -552,8 +552,8 @@ evalsubshell(union node *n, int flags)
forkshell(jp = makejob(n, 1), n, backgnd?FORK_BG:FORK_FG) == 0) {
if (backgnd)
flags &=~ EV_TESTED;
redirect(n->nredir.redirect, REDIR_KEEP);
INTON;
redirect(n->nredir.redirect, REDIR_KEEP);
evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
} else if (backgnd)
exitstatus = 0;
@ -1086,7 +1086,8 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
* child's address space is actually shared with the parent as
* we rely on this.
*/
if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) {
if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL &&
(!cmd->ncmd.backgnd || cmd->ncmd.redirect == NULL)) {
pid_t pid;
int serrno;