aboutsummaryrefslogtreecommitdiff
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
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
-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;
}
}