Use SOCK_STREAM for socketpair, not SOCK_DGRAM so we get consistent
semantics when the other end closes. This should make the conversion to poll() less problematic.
This commit is contained in:
32
src/exec.c
32
src/exec.c
@@ -255,7 +255,7 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
|
|||||||
* We communicate with the child over a bi-directional pair of sockets.
|
* We communicate with the child over a bi-directional pair of sockets.
|
||||||
* Parent sends signal info to child and child sends back wait status.
|
* Parent sends signal info to child and child sends back wait status.
|
||||||
*/
|
*/
|
||||||
if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
|
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
|
||||||
fatal(_("unable to create sockets"));
|
fatal(_("unable to create sockets"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -374,12 +374,7 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
|
|||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
/*
|
if (errno != EAGAIN) {
|
||||||
* If not logging I/O we may receive ECONNRESET when
|
|
||||||
* the command is executed and sv is closed.
|
|
||||||
* It is safe to ignore this.
|
|
||||||
*/
|
|
||||||
if (log_io && errno != EAGAIN) {
|
|
||||||
cstat->type = CMD_ERRNO;
|
cstat->type = CMD_ERRNO;
|
||||||
cstat->val = errno;
|
cstat->val = errno;
|
||||||
break;
|
break;
|
||||||
@@ -391,10 +386,18 @@ sudo_execute(struct command_details *details, struct command_status *cstat)
|
|||||||
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
sudo_debug_printf(SUDO_DEBUG_ERROR,
|
||||||
"failed to read child status: %s",
|
"failed to read child status: %s",
|
||||||
n ? "short read" : "EOF");
|
n ? "short read" : "EOF");
|
||||||
/* XXX - should set cstat */
|
/*
|
||||||
|
* If not logging I/O we may get EOF when the command is
|
||||||
|
* executed and sv is closed. It is safe to ignore this.
|
||||||
|
*/
|
||||||
|
if (log_io || n != 0) {
|
||||||
|
/* XXX - need new CMD_ type for monitor errors. */
|
||||||
|
cstat->type = CMD_ERRNO;
|
||||||
|
cstat->val = n ? EIO : ECONNRESET;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (cstat->type == CMD_PID) {
|
if (cstat->type == CMD_PID) {
|
||||||
/*
|
/*
|
||||||
* Once we know the command's pid we can unblock
|
* Once we know the command's pid we can unblock
|
||||||
@@ -505,17 +508,8 @@ dispatch_signals(int sv[2], pid_t child, int log_io, struct command_status *csta
|
|||||||
do {
|
do {
|
||||||
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 && !log_io) {
|
||||||
if (log_io) {
|
if (WIFSTOPPED(status)) {
|
||||||
/*
|
|
||||||
* 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 if the
|
|
||||||
* monitor dies, shut down the socketpair to force a
|
|
||||||
* select() notification.
|
|
||||||
*/
|
|
||||||
(void) shutdown(sv[0], SHUT_WR);
|
|
||||||
} else if (WIFSTOPPED(status)) {
|
|
||||||
/*
|
/*
|
||||||
* Save the controlling terminal's process group
|
* Save the controlling terminal's process group
|
||||||
* so we can restore it after we resume, if needed.
|
* so we can restore it after we resume, if needed.
|
||||||
|
@@ -1170,11 +1170,16 @@ exec_monitor(struct command_details *details, int backchannel)
|
|||||||
|
|
||||||
/* read command from backchannel, should be a signal */
|
/* read command from backchannel, should be a signal */
|
||||||
n = recv(backchannel, &cstmp, sizeof(cstmp), 0);
|
n = recv(backchannel, &cstmp, sizeof(cstmp), 0);
|
||||||
|
if (n != sizeof(cstmp)) {
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
warning(_("error reading from socketpair"));
|
warning(_("error reading from socketpair"));
|
||||||
goto done;
|
goto done;
|
||||||
|
} else {
|
||||||
|
/* /* short read or EOF, parent process died? */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cstmp.type != CMD_SIGNO) {
|
if (cstmp.type != CMD_SIGNO) {
|
||||||
warningx(_("unexpected reply type on backchannel: %d"),
|
warningx(_("unexpected reply type on backchannel: %d"),
|
||||||
|
Reference in New Issue
Block a user