diff options
author | David Hotham <david.hotham@metaswitch.com> | 2018-07-12 22:38:07 +0100 |
---|---|---|
committer | David Hotham <david.hotham@metaswitch.com> | 2018-07-13 20:56:04 +0100 |
commit | fe913d7838d382075c1dfa8bbf2e652a49b57909 (patch) | |
tree | 84521e253f64ef307b14cb184985391da1b2caf2 /src/nvim/os/pty_process_unix.c | |
parent | 01570f1ff3c402af9a9a48c2cca2c5a830c08315 (diff) | |
download | rneovim-fe913d7838d382075c1dfa8bbf2e652a49b57909.tar.gz rneovim-fe913d7838d382075c1dfa8bbf2e652a49b57909.tar.bz2 rneovim-fe913d7838d382075c1dfa8bbf2e652a49b57909.zip |
Only waitpid() for processes that we care about
It seems as though in an AppImage there's an extra child process that
dies at some early point, before we have set up a SIGCHLD handler. So
when we later get a SIGCHLD from a child that we do care about,
waitpid(-1, ...) tells us about the extra child - and we don't notice
that the interesting child has exited.
Or something like that!
See also:
* https://patchwork.kernel.org/patch/9949491/ in which perf hit
something similar
* discussion at the AppImage repository:
https://github.com/AppImage/AppImageKit/issues/812#issuecomment-404662110.
Fix is to be explicit about which process we are waitpid()'ing for, so
we never need be distracted by children that we don't know about.
Fixes #8104
Diffstat (limited to 'src/nvim/os/pty_process_unix.c')
-rw-r--r-- | src/nvim/os/pty_process_unix.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index bd23596ea7..2aeaafe4bd 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -273,26 +273,24 @@ static void chld_handler(uv_signal_t *handle, int signum) int stat = 0; int pid; - do { - pid = waitpid(-1, &stat, WNOHANG); - } while (pid < 0 && errno == EINTR); - - if (pid <= 0) { - return; - } - Loop *loop = handle->loop->data; kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; - if (proc->pid == pid) { - if (WIFEXITED(stat)) { - proc->status = WEXITSTATUS(stat); - } else if (WIFSIGNALED(stat)) { - proc->status = WTERMSIG(stat); - } - proc->internal_exit_cb(proc); - break; + do { + pid = waitpid(proc->pid, &stat, WNOHANG); + } while (pid < 0 && errno == EINTR); + + if (pid <= 0) { + continue; + } + + if (WIFEXITED(stat)) { + proc->status = WEXITSTATUS(stat); + } else if (WIFSIGNALED(stat)) { + proc->status = WTERMSIG(stat); } + proc->internal_exit_cb(proc); + break; } } |