Linux select() may return ENOMEM if there is a kernel resource
shortage. Older Solaris select() may return EIO instead of EBADF when the tty goes away. If we get an unhandled select() failure, kill the child and exit cleanly.
This commit is contained in:
11
src/exec.c
11
src/exec.c
@@ -335,13 +335,18 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
|
|||||||
nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
|
nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
|
||||||
sudo_debug_printf(SUDO_DEBUG_DEBUG, "select returns %d", nready);
|
sudo_debug_printf(SUDO_DEBUG_DEBUG, "select returns %d", nready);
|
||||||
if (nready == -1) {
|
if (nready == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR || errno == ENOMEM)
|
||||||
continue;
|
continue;
|
||||||
if (errno == EBADF) {
|
if (errno == EBADF || errno == EIO) {
|
||||||
/* One of the ttys must have gone away. */
|
/* One of the ttys must have gone away. */
|
||||||
goto do_tty_io;
|
goto do_tty_io;
|
||||||
}
|
}
|
||||||
error(1, _("select failed"));
|
warning(_("select failed"));
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
|
"select failure, terminating child");
|
||||||
|
schedule_signal(SIGKILL);
|
||||||
|
forward_signals(sv[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (FD_ISSET(sv[0], fdsw)) {
|
if (FD_ISSET(sv[0], fdsw)) {
|
||||||
forward_signals(sv[0]);
|
forward_signals(sv[0]);
|
||||||
|
@@ -1015,9 +1015,10 @@ exec_monitor(struct command_details *details, int backchannel)
|
|||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (errno == EINTR)
|
if (errno == EINTR || errno == ENOMEM)
|
||||||
continue;
|
continue;
|
||||||
error(1, "monitor: %s", _("select failed"));
|
warning("monitor: %s", _("select failed"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(signal_pipe[0], fdsr)) {
|
if (FD_ISSET(signal_pipe[0], fdsr)) {
|
||||||
@@ -1152,11 +1153,11 @@ flush_output(void)
|
|||||||
if (nready <= 0) {
|
if (nready <= 0) {
|
||||||
if (nready == 0)
|
if (nready == 0)
|
||||||
break; /* all I/O flushed */
|
break; /* all I/O flushed */
|
||||||
if (errno == EINTR)
|
if (errno == EINTR || errno == ENOMEM)
|
||||||
continue;
|
continue;
|
||||||
error(1, _("select failed"));
|
warning(_("select failed"));
|
||||||
}
|
}
|
||||||
if (perform_io(fdsr, fdsw, NULL) != 0)
|
if (perform_io(fdsr, fdsw, NULL) != 0 || nready == -1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
efree(fdsr);
|
efree(fdsr);
|
||||||
|
Reference in New Issue
Block a user