Explicitly check for a continued process with waitpid(2). Otherwise,
waitpid() will return 0 when the command is resumed after being suspended, which we were treating the same as -1. Fixes suspend and resume on Linux and probably others.
This commit is contained in:
@@ -1148,13 +1148,14 @@ static bool
|
||||
handle_sigchld(int backchannel, struct command_status *cstat)
|
||||
{
|
||||
char signame[SIG2STR_MAX];
|
||||
bool alive = true;
|
||||
int status;
|
||||
pid_t pid;
|
||||
debug_decl(handle_sigchld, SUDO_DEBUG_EXEC);
|
||||
|
||||
/* Read command status. */
|
||||
do {
|
||||
pid = waitpid(cmnd_pid, &status, WUNTRACED|WNOHANG);
|
||||
pid = waitpid(cmnd_pid, &status, WUNTRACED|WCONTINUED|WNOHANG);
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
if (pid <= 0) {
|
||||
sudo_debug_printf(SUDO_DEBUG_DIAG,
|
||||
@@ -1162,17 +1163,23 @@ handle_sigchld(int backchannel, struct command_status *cstat)
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
if (WIFSTOPPED(status)) {
|
||||
if (WIFCONTINUED(status)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command (%d) resumed", cmnd_pid);
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
if (sig2str(WSTOPSIG(status), signame) == -1)
|
||||
snprintf(signame, sizeof(signame), "%d", WSTOPSIG(status));
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command stopped, SIG%s", signame);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command (%d) stopped, SIG%s",
|
||||
cmnd_pid, signame);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
if (sig2str(WTERMSIG(status), signame) == -1)
|
||||
snprintf(signame, sizeof(signame), "%d", WTERMSIG(status));
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command killed, SIG%s", signame);
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command (%d) killed, SIG%s",
|
||||
cmnd_pid, signame);
|
||||
alive = false;
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command exited: %d",
|
||||
WEXITSTATUS(status));
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, "command (%d) exited: %d",
|
||||
cmnd_pid, WEXITSTATUS(status));
|
||||
alive = false;
|
||||
}
|
||||
|
||||
/* Don't overwrite execve() failure with child exit status. */
|
||||
@@ -1189,12 +1196,10 @@ handle_sigchld(int backchannel, struct command_status *cstat)
|
||||
} while (pid == -1 && errno == EINTR);
|
||||
if (pid != mon_pgrp)
|
||||
send_status(backchannel, cstat);
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* It's dead, Jim. */
|
||||
debug_return_bool(false);
|
||||
debug_return_bool(alive);
|
||||
}
|
||||
|
||||
struct monitor_closure {
|
||||
|
Reference in New Issue
Block a user