Bug fix: deal with race-like (select(2) vs wait4(2)) error flow bogon.
This commit is contained in:
parent
5d25794ed2
commit
ac722a849a
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: run.c,v 1.10 1999/03/11 16:48:27 marc Exp $ */
|
/* $NetBSD: run.c,v 1.11 1999/03/22 09:02:47 ross Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 1997 Piermont Information Systems Inc.
|
* Copyright 1997 Piermont Information Systems Inc.
|
||||||
@ -260,6 +260,7 @@ launch_subwin(actionwin, args, win, display)
|
|||||||
{
|
{
|
||||||
int xcor,ycor;
|
int xcor,ycor;
|
||||||
int n, i, j;
|
int n, i, j;
|
||||||
|
int selectfailed;
|
||||||
int status, master, slave;
|
int status, master, slave;
|
||||||
fd_set active_fd_set, read_fd_set;
|
fd_set active_fd_set, read_fd_set;
|
||||||
int dataflow[2];
|
int dataflow[2];
|
||||||
@ -290,7 +291,7 @@ launch_subwin(actionwin, args, win, display)
|
|||||||
case -1:
|
case -1:
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
case 0: {
|
case 0:
|
||||||
(void)close(STDIN_FILENO);
|
(void)close(STDIN_FILENO);
|
||||||
subchild = fork();
|
subchild = fork();
|
||||||
if (subchild == 0) {
|
if (subchild == 0) {
|
||||||
@ -321,9 +322,9 @@ launch_subwin(actionwin, args, win, display)
|
|||||||
execvp(argzero, origargs);
|
execvp(argzero, origargs);
|
||||||
/* the parent will see this as the output from the
|
/* the parent will see this as the output from the
|
||||||
child */
|
child */
|
||||||
perror("execvp");
|
warn("execvp %s", argzero);
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
} break; /* end of child */
|
break; /* end of child */
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
close(dataflow[1]);
|
close(dataflow[1]);
|
||||||
@ -332,15 +333,20 @@ launch_subwin(actionwin, args, win, display)
|
|||||||
FD_SET(STDIN_FILENO, &active_fd_set);
|
FD_SET(STDIN_FILENO, &active_fd_set);
|
||||||
|
|
||||||
pid = wait4(child, &status, WNOHANG, 0);
|
pid = wait4(child, &status, WNOHANG, 0);
|
||||||
for (;;) {
|
for (selectfailed = 0;;) {
|
||||||
|
if (selectfailed) {
|
||||||
|
char *msg = "select(2) failed but no child died?";
|
||||||
|
if(logging)
|
||||||
|
(void)fprintf(log, msg);
|
||||||
|
errx(1, msg);
|
||||||
|
}
|
||||||
read_fd_set = active_fd_set;
|
read_fd_set = active_fd_set;
|
||||||
if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
|
if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
|
||||||
perror("select");
|
perror("select");
|
||||||
if (logging)
|
if (logging)
|
||||||
(void)fprintf(log, "select failure: %s\n", strerror(errno));
|
(void)fprintf(log, "select failure: %s\n", strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
++selectfailed;
|
||||||
}
|
} else for (i = 0; i < FD_SETSIZE; ++i) {
|
||||||
for (i = 0; i < FD_SETSIZE; ++i)
|
|
||||||
if (FD_ISSET (i, &read_fd_set)) {
|
if (FD_ISSET (i, &read_fd_set)) {
|
||||||
n = read(i, ibuf, MAXBUF);
|
n = read(i, ibuf, MAXBUF);
|
||||||
if (i == STDIN_FILENO)
|
if (i == STDIN_FILENO)
|
||||||
@ -377,6 +383,7 @@ launch_subwin(actionwin, args, win, display)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pid = wait4(child, &status, WNOHANG, 0);
|
pid = wait4(child, &status, WNOHANG, 0);
|
||||||
if (pid == child && (WIFEXITED(status) || WIFSIGNALED(status)))
|
if (pid == child && (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user