No longer need to check for explicit death of the child (process #2)
since if it dies we will get EPIPE from the socketpair. Fix a sizeof() that was causing a spurious error. Convert SCRIPT_DEBUG to sudo_debug.
This commit is contained in:
51
src/script.c
51
src/script.c
@@ -91,7 +91,6 @@ static int script_fds[3];
|
|||||||
static int ttyout;
|
static int ttyout;
|
||||||
|
|
||||||
/* XXX - use an array of signals instead of just a single variable */
|
/* XXX - use an array of signals instead of just a single variable */
|
||||||
static sig_atomic_t alive = 1;
|
|
||||||
static sig_atomic_t recvsig = 0;
|
static sig_atomic_t recvsig = 0;
|
||||||
static sig_atomic_t ttymode = TERM_COOKED;
|
static sig_atomic_t ttymode = TERM_COOKED;
|
||||||
static sig_atomic_t tty_initialized = 0;
|
static sig_atomic_t tty_initialized = 0;
|
||||||
@@ -221,9 +220,7 @@ suspend_parent(int signo, struct script_buf *output)
|
|||||||
/* Suspend self and continue child when we resume. */
|
/* Suspend self and continue child when we resume. */
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sigaction(signo, &sa, &osa);
|
sigaction(signo, &sa, &osa);
|
||||||
#ifdef SCRIPT_DEBUG
|
sudo_debug(8, "kill parent %d", signo);
|
||||||
warningx("kill parent %d", signo);
|
|
||||||
#endif
|
|
||||||
kill(parent, signo);
|
kill(parent, signo);
|
||||||
|
|
||||||
/* Check foreground/background status on resume. */
|
/* Check foreground/background status on resume. */
|
||||||
@@ -233,10 +230,8 @@ suspend_parent(int signo, struct script_buf *output)
|
|||||||
* Only modify term if we are foreground process and either
|
* Only modify term if we are foreground process and either
|
||||||
* the old tty mode was not cooked or child got SIGTT{IN,OU}
|
* the old tty mode was not cooked or child got SIGTT{IN,OU}
|
||||||
*/
|
*/
|
||||||
#ifdef SCRIPT_DEBUG
|
sudo_debug(8, "parent is in %sground, ttymode %d -> %d",
|
||||||
warningx("parent is in %sground, ttymode %d -> %d",
|
|
||||||
foreground ? "fore" : "back", oldmode, ttymode);
|
foreground ? "fore" : "back", oldmode, ttymode);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ttymode != TERM_COOKED) {
|
if (ttymode != TERM_COOKED) {
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
@@ -420,7 +415,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
fdsw = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
|
fdsw = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
|
||||||
zero_bytes(&input, sizeof(input));
|
zero_bytes(&input, sizeof(input));
|
||||||
zero_bytes(&output, sizeof(output));
|
zero_bytes(&output, sizeof(output));
|
||||||
while (alive) {
|
for (;;) {
|
||||||
/* XXX - racey */
|
/* XXX - racey */
|
||||||
if (!relaysig && recvsig != SIGCHLD) {
|
if (!relaysig && recvsig != SIGCHLD) {
|
||||||
relaysig = recvsig;
|
relaysig = recvsig;
|
||||||
@@ -459,17 +454,16 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN) {
|
||||||
break;
|
/* Did the other end of the pipe go away? */
|
||||||
} else if (n != sizeof(*cstat)) {
|
cstat->type = CMD_ERRNO;
|
||||||
break; /* EOF? */
|
cstat->val = errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cstat->type == CMD_WSTATUS) {
|
if (cstat->type == CMD_WSTATUS) {
|
||||||
if (WIFSTOPPED(cstat->val)) {
|
if (WIFSTOPPED(cstat->val)) {
|
||||||
/* Suspend parent and tell child how to resume on return. */
|
/* Suspend parent and tell child how to resume on return. */
|
||||||
#ifdef SCRIPT_DEBUG
|
sudo_debug(8, "child stopped, suspending parent");
|
||||||
warningx("child stopped, suspending parent");
|
|
||||||
#endif
|
|
||||||
relaysig = suspend_parent(WSTOPSIG(cstat->val), &output);
|
relaysig = suspend_parent(WSTOPSIG(cstat->val), &output);
|
||||||
/* XXX - write relaysig immediately? */
|
/* XXX - write relaysig immediately? */
|
||||||
continue;
|
continue;
|
||||||
@@ -478,19 +472,20 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (cstat->type == CMD_ERRNO) {
|
} else if (cstat->type == CMD_ERRNO) {
|
||||||
/* Child was unable to execute command. */
|
/* Child was unable to execute command or broken pipe. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FD_ISSET(sv[0], fdsw)) {
|
if (FD_ISSET(sv[0], fdsw)) {
|
||||||
/* XXX - we rely on child to be suspended before we suspend us */
|
/* XXX - we rely on child to be suspended before we suspend us */
|
||||||
|
sudo_debug(9, "sending signal %d to child over backchannel", relaysig);
|
||||||
cstat->type = CMD_SIGNO;
|
cstat->type = CMD_SIGNO;
|
||||||
cstat->val = relaysig;
|
cstat->val = relaysig;
|
||||||
relaysig = 0;
|
relaysig = 0;
|
||||||
do {
|
do {
|
||||||
n = send(sv[0], cstat, sizeof(*cstat), 0);
|
n = send(sv[0], cstat, sizeof(*cstat), 0);
|
||||||
} while (n == -1 && errno == EINTR);
|
} while (n == -1 && errno == EINTR);
|
||||||
if (n != sizeof(relaysig)) {
|
if (n != sizeof(cstat)) {
|
||||||
break; /* should not happen */
|
break; /* should not happen */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -550,7 +545,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush any remaining output to stdout (already updated output file). */
|
/* Flush any remaining output to stdout (already sent to I/O modules). */
|
||||||
n = fcntl(STDOUT_FILENO, F_GETFL, 0);
|
n = fcntl(STDOUT_FILENO, F_GETFL, 0);
|
||||||
if (n != -1) {
|
if (n != -1) {
|
||||||
n &= ~O_NONBLOCK;
|
n &= ~O_NONBLOCK;
|
||||||
@@ -696,14 +691,12 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
pid = waitpid(child, &status, WUNTRACED|WNOHANG);
|
pid = waitpid(child, &status, WUNTRACED|WNOHANG);
|
||||||
} while (pid == -1 && errno == EINTR);
|
} while (pid == -1 && errno == EINTR);
|
||||||
if (pid == child) {
|
if (pid == child) {
|
||||||
#ifdef SCRIPT_DEBUG
|
|
||||||
if (WIFSTOPPED(status))
|
if (WIFSTOPPED(status))
|
||||||
warningx("command stopped, signal %d", WSTOPSIG(status));
|
sudo_debug(8, "command stopped, signal %d", WSTOPSIG(status));
|
||||||
else if (WIFSIGNALED(status))
|
else if (WIFSIGNALED(status))
|
||||||
warningx("command killed, signal %d", WTERMSIG(status));
|
sudo_debug(8, "command killed, signal %d", WTERMSIG(status));
|
||||||
else
|
else
|
||||||
warningx("command exited?");
|
sudo_debug(8, "command exited: %d", WEXITSTATUS(status));
|
||||||
#endif
|
|
||||||
cstat.type = CMD_WSTATUS;
|
cstat.type = CMD_WSTATUS;
|
||||||
cstat.val = status;
|
cstat.val = status;
|
||||||
do {
|
do {
|
||||||
@@ -711,9 +704,7 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
} while (n == -1 && errno == EINTR);
|
} while (n == -1 && errno == EINTR);
|
||||||
if (n != sizeof(cstat))
|
if (n != sizeof(cstat))
|
||||||
break; /* XXX - error, kill child and exit */
|
break; /* XXX - error, kill child and exit */
|
||||||
#ifdef SCRIPT_DEBUG
|
sudo_debug(8, "sent wait status to parent");
|
||||||
warningx("sent wait status to parent");
|
|
||||||
#endif
|
|
||||||
if (!WIFSTOPPED(status)) {
|
if (!WIFSTOPPED(status)) {
|
||||||
/* XXX */
|
/* XXX */
|
||||||
_exit(1); /* child dead */
|
_exit(1); /* child dead */
|
||||||
@@ -743,9 +734,7 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int
|
|||||||
signo = cstat.val;
|
signo = cstat.val;
|
||||||
|
|
||||||
/* Handle signal from parent. */
|
/* Handle signal from parent. */
|
||||||
#ifdef SCRIPT_DEBUG
|
sudo_debug(8, "signal %d from parent", signo);
|
||||||
warningx("signal %d from parent", signo);
|
|
||||||
#endif
|
|
||||||
switch (signo) {
|
switch (signo) {
|
||||||
case SIGKILL:
|
case SIGKILL:
|
||||||
_exit(1); /* XXX */
|
_exit(1); /* XXX */
|
||||||
@@ -866,6 +855,8 @@ sync_winsize(int src, int dst)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Handler for SIGCHLD in parent
|
* Handler for SIGCHLD in parent
|
||||||
|
* Note that this will detect when the child monitoring the command exits,
|
||||||
|
* not the command itself.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
sigchild(int s)
|
sigchild(int s)
|
||||||
@@ -879,8 +870,6 @@ sigchild(int s)
|
|||||||
if (pid == child) {
|
if (pid == child) {
|
||||||
if (WIFSTOPPED(child_status))
|
if (WIFSTOPPED(child_status))
|
||||||
recvsig = WSTOPSIG(child_status);
|
recvsig = WSTOPSIG(child_status);
|
||||||
else
|
|
||||||
alive = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
|
Reference in New Issue
Block a user