summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2017-02-02 13:20:29 -0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2017-02-02 13:20:29 -0800
commit5816d3cdfbfbeb5d173114ed08ab5c04c63207a6 (patch)
tree9dd715cb97d94c144e10bd7aef47d69eedf668c2 /run-command.c
parentReady for 2.11.1 (diff)
parentexecv_dashed_external: wait for child on signal death (diff)
downloadtgif-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.c19
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);
}