summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git.c1
-rw-r--r--run-command.c19
-rw-r--r--run-command.h1
3 files changed, 21 insertions, 0 deletions
diff --git a/git.c b/git.c
index bc2f2a7ec9..c8fe6637df 100644
--- a/git.c
+++ b/git.c
@@ -588,6 +588,7 @@ static void execv_dashed_external(const char **argv)
argv_array_pushf(&cmd.args, "git-%s", argv[0]);
argv_array_pushv(&cmd.args, argv + 1);
cmd.clean_on_exit = 1;
+ cmd.wait_after_clean = 1;
cmd.silent_exec_failure = 1;
trace_argv_printf(cmd.args.argv, "trace: exec:");
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);
}
diff --git a/run-command.h b/run-command.h
index dd1c78c28d..4fa8f65adb 100644
--- a/run-command.h
+++ b/run-command.h
@@ -43,6 +43,7 @@ struct child_process {
unsigned stdout_to_stderr:1;
unsigned use_shell:1;
unsigned clean_on_exit:1;
+ unsigned wait_after_clean:1;
void (*clean_on_exit_handler)(struct child_process *process);
void *clean_on_exit_handler_cbdata;
};