diff options
author | Junio C Hamano <gitster@pobox.com> | 2017-02-02 13:20:29 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-02-02 13:20:29 -0800 |
commit | 5816d3cdfbfbeb5d173114ed08ab5c04c63207a6 (patch) | |
tree | 9dd715cb97d94c144e10bd7aef47d69eedf668c2 /run-command.c | |
parent | Ready for 2.11.1 (diff) | |
parent | execv_dashed_external: wait for child on signal death (diff) | |
download | tgif-5816d3cdfbfbeb5d173114ed08ab5c04c63207a6.tar.xz |
Merge branch 'jk/execv-dashed-external' into maint
Typing ^C to pager, which usually does not kill it, killed Git and
took the pager down as a collateral damage in certain process-tree
structure. This has been fixed.
* jk/execv-dashed-external:
execv_dashed_external: wait for child on signal death
execv_dashed_external: stop exiting with negative code
execv_dashed_external: use child_process struct
Diffstat (limited to 'run-command.c')
-rw-r--r-- | run-command.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/run-command.c b/run-command.c index ca905a9e80..73bfba7ef9 100644 --- a/run-command.c +++ b/run-command.c @@ -29,6 +29,8 @@ static int installed_child_cleanup_handler; static void cleanup_children(int sig, int in_signal) { + struct child_to_clean *children_to_wait_for = NULL; + while (children_to_clean) { struct child_to_clean *p = children_to_clean; children_to_clean = p->next; @@ -45,6 +47,23 @@ static void cleanup_children(int sig, int in_signal) } kill(p->pid, sig); + + if (p->process->wait_after_clean) { + p->next = children_to_wait_for; + children_to_wait_for = p; + } else { + if (!in_signal) + free(p); + } + } + + while (children_to_wait_for) { + struct child_to_clean *p = children_to_wait_for; + children_to_wait_for = p->next; + + while (waitpid(p->pid, NULL, 0) < 0 && errno == EINTR) + ; /* spin waiting for process exit or error */ + if (!in_signal) free(p); } |