TQ_DECLARE(sigforward)
static struct sigforward_list sigfwd_list;
-static int handle_signals(int fd, pid_t child, int log_io,
+static int handle_signals(int sv[2], pid_t child, int log_io,
struct command_status *cstat);
static void forward_signals(int fd);
static void schedule_signal(int signo);
forward_signals(sv[0]);
}
if (FD_ISSET(signal_pipe[0], fdsr)) {
- n = handle_signals(signal_pipe[0], child, log_io, cstat);
+ n = handle_signals(sv, child, log_io, cstat);
if (n == 0) {
/* Child has exited, cstat is set, we are done. */
break;
* Returns -1 on error, 0 on child exit, else 1.
*/
static int
-handle_signals(int fd, pid_t child, int log_io, struct command_status *cstat)
+handle_signals(int sv[2], pid_t child, int log_io, struct command_status *cstat)
{
unsigned char signo;
ssize_t nread;
/*
* On BSD we get ECONNRESET on sv[0] if monitor dies
* and select() will return with sv[0] readable.
- * On Linux that doesn't appear to happen so we
- * treat the monitor dying as a fatal error.
- * Note that the wait status we return is that of
- * the monitor and not the command; unfortunately
- * that is the best that we can do here.
+ * On Linux that doesn't appear to happen so if the
+ * monitor dies, shut down the socketpair to force a
+ * select() notification.
*/
- if (!WIFSTOPPED(status)) {
- cstat->type = CMD_WSTATUS;
- cstat->val = status;
- debug_return_int(0);
- }
+ (void) shutdown(sv[0], SHUT_WR);
} else {
if (WIFSTOPPED(status)) {
/*
switch (cstat.type) {
case CMD_ERRNO:
/* exec_setup() or execve() returned an error. */
- sudo_debug_printf(SUDO_DEBUG_DEBUG, "calling policy close with errno");
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "calling policy close with errno %d", cstat.val);
policy_close(&policy_plugin, 0, cstat.val);
tq_foreach_fwd(&io_plugins, plugin) {
- sudo_debug_printf(SUDO_DEBUG_DEBUG, "calling I/O close with errno");
+ sudo_debug_printf(SUDO_DEBUG_DEBUG,
+ "calling I/O close with errno %d", cstat.val);
iolog_close(plugin, 0, cstat.val);
}
exitcode = 1;
case CMD_WSTATUS:
/* Command ran, exited or was killed. */
sudo_debug_printf(SUDO_DEBUG_DEBUG,
- "calling policy close with wait status");
+ "calling policy close with wait status %d", cstat.val);
policy_close(&policy_plugin, cstat.val, 0);
tq_foreach_fwd(&io_plugins, plugin) {
sudo_debug_printf(SUDO_DEBUG_DEBUG,
- "calling I/O close with wait status");
+ "calling I/O close with wait status %d", cstat.val);
iolog_close(plugin, cstat.val, 0);
}
if (WIFEXITED(cstat.val))