aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/pty_process_unix.c
diff options
context:
space:
mode:
authorDavid Hotham <david.hotham@metaswitch.com>2018-07-12 22:38:07 +0100
committerDavid Hotham <david.hotham@metaswitch.com>2018-07-13 20:56:04 +0100
commitfe913d7838d382075c1dfa8bbf2e652a49b57909 (patch)
tree84521e253f64ef307b14cb184985391da1b2caf2 /src/nvim/os/pty_process_unix.c
parent01570f1ff3c402af9a9a48c2cca2c5a830c08315 (diff)
downloadrneovim-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.c30
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;
}
}