зеркало из https://github.com/github/putty.git
uxpty: propagate exit code more reliably on pty EIO.
There was a bit of a race condition depending on whether uxpty spotted the EOF/EIO on the process's output first, or the SIGCHLD for its actual termination: if the former came first, it would never bother to reap the exit code at all. It still doesn't bother if it's closing the session immediately and the process genuinely _hasn't_ died (say, if it detaches itself completely from the controlling tty to run in the background like a weird parody of an old DOS TSR). But now when we see EOF, we make an immediate (but nonblocking) attempt to wait for the child process, in case its exit code was already available and we just hadn't noticed yet.
This commit is contained in:
Родитель
c970d2b694
Коммит
0ee204f699
32
unix/uxpty.c
32
unix/uxpty.c
|
@ -580,7 +580,9 @@ void pty_pre_init(void)
|
|||
|
||||
}
|
||||
|
||||
void pty_real_select_result(Pty *pty, int event, int status)
|
||||
static void pty_try_wait(void);
|
||||
|
||||
static void pty_real_select_result(Pty *pty, int event, int status)
|
||||
{
|
||||
char buf[4096];
|
||||
int ret;
|
||||
|
@ -627,6 +629,7 @@ void pty_real_select_result(Pty *pty, int event, int status)
|
|||
* the pterm window to hang around!
|
||||
*/
|
||||
finished = TRUE;
|
||||
pty_try_wait(); /* one last effort to collect exit code */
|
||||
if (!pty->child_dead)
|
||||
pty->exit_code = 0;
|
||||
} else if (ret < 0) {
|
||||
|
@ -683,27 +686,34 @@ void pty_real_select_result(Pty *pty, int event, int status)
|
|||
}
|
||||
}
|
||||
|
||||
static void pty_try_wait(void)
|
||||
{
|
||||
Pty *pty;
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
|
||||
pty = find234(ptys_by_pid, &pid, pty_find_by_pid);
|
||||
|
||||
if (pty)
|
||||
pty_real_select_result(pty, -1, status);
|
||||
} while (pid > 0);
|
||||
}
|
||||
|
||||
void pty_select_result(int fd, int event)
|
||||
{
|
||||
Pty *pty;
|
||||
|
||||
if (fd == pty_signal_pipe[0]) {
|
||||
pid_t pid;
|
||||
int status;
|
||||
char c[1];
|
||||
|
||||
if (read(pty_signal_pipe[0], c, 1) <= 0)
|
||||
/* ignore error */;
|
||||
/* ignore its value; it'll be `x' */
|
||||
|
||||
do {
|
||||
pid = waitpid(-1, &status, WNOHANG);
|
||||
|
||||
pty = find234(ptys_by_pid, &pid, pty_find_by_pid);
|
||||
|
||||
if (pty)
|
||||
pty_real_select_result(pty, -1, status);
|
||||
} while (pid > 0);
|
||||
pty_try_wait();
|
||||
} else {
|
||||
pty = find234(ptys_by_fd, &fd, pty_find_by_fd);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче