Close the pty slave in the parent so that when the command and
monitor exit, the pty gets recycled without our having to close it directly.
This commit is contained in:
@@ -594,6 +594,15 @@ exec_monitor(struct command_details *details, sigset_t *oset,
|
|||||||
if (pipe2(errpipe, O_CLOEXEC) != 0)
|
if (pipe2(errpipe, O_CLOEXEC) != 0)
|
||||||
sudo_fatal(U_("unable to create pipe"));
|
sudo_fatal(U_("unable to create pipe"));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before forking, wait for the main sudo process to tell us to go.
|
||||||
|
* Avoids race conditions when the command exits quickly.
|
||||||
|
*/
|
||||||
|
while (recv(backchannel, &cstat, sizeof(cstat), MSG_WAITALL) == -1) {
|
||||||
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
|
sudo_fatal(U_("unable to receive message from parent"));
|
||||||
|
}
|
||||||
|
|
||||||
mc.cmnd_pid = sudo_debug_fork();
|
mc.cmnd_pid = sudo_debug_fork();
|
||||||
switch (mc.cmnd_pid) {
|
switch (mc.cmnd_pid) {
|
||||||
case -1:
|
case -1:
|
||||||
|
@@ -744,23 +744,15 @@ io_buf_new(int rfd, int wfd,
|
|||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We already closed the slave pty so reads from the master will not block.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
pty_close(struct command_status *cstat)
|
pty_finish(struct command_status *cstat)
|
||||||
{
|
{
|
||||||
struct io_buffer *iob;
|
struct io_buffer *iob;
|
||||||
int n;
|
int n;
|
||||||
debug_decl(pty_close, SUDO_DEBUG_EXEC);
|
debug_decl(pty_finish, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
#ifndef _AIX
|
|
||||||
/*
|
|
||||||
* Close the pty slave first so reads from the master don't block.
|
|
||||||
* On AIX as it will cause us to lose *our* controlling tty too!
|
|
||||||
*/
|
|
||||||
if (io_fds[SFD_SLAVE] != -1) {
|
|
||||||
close(io_fds[SFD_SLAVE]);
|
|
||||||
io_fds[SFD_SLAVE] = -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Flush any remaining output (the plugin already got it). */
|
/* Flush any remaining output (the plugin already got it). */
|
||||||
if (io_fds[SFD_USERTTY] != -1) {
|
if (io_fds[SFD_USERTTY] != -1) {
|
||||||
@@ -790,14 +782,6 @@ pty_close(struct command_status *cstat)
|
|||||||
if (utmp_user != NULL)
|
if (utmp_user != NULL)
|
||||||
utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0);
|
utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0);
|
||||||
|
|
||||||
#ifndef _AIX
|
|
||||||
/* Close pty master. */
|
|
||||||
if (io_fds[SFD_MASTER] != -1) {
|
|
||||||
close(io_fds[SFD_MASTER]);
|
|
||||||
io_fds[SFD_MASTER] = -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debug_return;
|
debug_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1421,12 +1405,13 @@ exec_pty(struct command_details *details, struct command_status *cstat)
|
|||||||
if (!sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
|
if (!sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE])) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
"%s: unable to copy terminal settings to pty", __func__);
|
"%s: unable to copy terminal settings to pty", __func__);
|
||||||
}
|
foreground = false;
|
||||||
|
} else {
|
||||||
/* Start out in raw mode unless part of a pipeline or backgrounded. */
|
/* Start in raw mode unless part of a pipeline or backgrounded. */
|
||||||
if (!pipeline && !ISSET(details->flags, CD_EXEC_BG)) {
|
if (!pipeline && !ISSET(details->flags, CD_EXEC_BG)) {
|
||||||
if (sudo_term_raw(io_fds[SFD_USERTTY], 0))
|
if (sudo_term_raw(io_fds[SFD_USERTTY], 0))
|
||||||
ttymode = TERM_RAW;
|
ttymode = TERM_RAW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,6 +1460,24 @@ exec_pty(struct command_details *details, struct command_status *cstat)
|
|||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We close the pty slave so only the monitor and command have a
|
||||||
|
* reference to it. This ensures that we can don't block reading
|
||||||
|
* from the master when the command and monitor have exited.
|
||||||
|
*/
|
||||||
|
if (io_fds[SFD_SLAVE] != -1) {
|
||||||
|
close(io_fds[SFD_SLAVE]);
|
||||||
|
io_fds[SFD_SLAVE] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the monitor to continue now that the slave is closed. */
|
||||||
|
cstat->type = CMD_SIGNO;
|
||||||
|
cstat->val = 0;
|
||||||
|
while (send(sv[0], cstat, sizeof(*cstat), 0) == -1) {
|
||||||
|
if (errno != EINTR && errno != EAGAIN)
|
||||||
|
sudo_fatal(U_("unable to send message to monitor process"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Close the other end of the stdin/stdout/stderr pipes and socketpair. */
|
/* Close the other end of the stdin/stdout/stderr pipes and socketpair. */
|
||||||
if (io_pipe[STDIN_FILENO][0] != -1)
|
if (io_pipe[STDIN_FILENO][0] != -1)
|
||||||
close(io_pipe[STDIN_FILENO][0]);
|
close(io_pipe[STDIN_FILENO][0]);
|
||||||
@@ -1523,7 +1526,7 @@ exec_pty(struct command_details *details, struct command_status *cstat)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Flush any remaining output, free I/O bufs and events, do logout. */
|
/* Flush any remaining output, free I/O bufs and events, do logout. */
|
||||||
pty_close(cstat);
|
pty_finish(cstat);
|
||||||
|
|
||||||
/* Free things up. */
|
/* Free things up. */
|
||||||
free_exec_closure_pty(&ec);
|
free_exec_closure_pty(&ec);
|
||||||
|
Reference in New Issue
Block a user