Skip to content

Commit ac2fbaa

Browse files
larsxschneidergitster
authored andcommitted
run-command: add clean_on_exit_handler
Some processes might want to perform cleanup tasks before Git kills them due to the 'clean_on_exit' flag. Let's give them an interface for doing this. The feature is used in a subsequent patch. Please note, that the cleanup callback is not executed if Git dies of a signal. The reason is that only "async-signal-safe" functions would be allowed to be call in that case. Since we cannot control what functions the callback will use, we will not support the case. See 507d780 for more details. Helped-by: Johannes Sixt <[email protected]> Signed-off-by: Lars Schneider <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b992fe1 commit ac2fbaa

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

run-command.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void child_process_clear(struct child_process *child)
2121

2222
struct child_to_clean {
2323
pid_t pid;
24+
struct child_process *process;
2425
struct child_to_clean *next;
2526
};
2627
static struct child_to_clean *children_to_clean;
@@ -31,6 +32,18 @@ static void cleanup_children(int sig, int in_signal)
3132
while (children_to_clean) {
3233
struct child_to_clean *p = children_to_clean;
3334
children_to_clean = p->next;
35+
36+
if (p->process && !in_signal) {
37+
struct child_process *process = p->process;
38+
if (process->clean_on_exit_handler) {
39+
trace_printf(
40+
"trace: run_command: running exit handler for pid %"
41+
PRIuMAX, (uintmax_t)p->pid
42+
);
43+
process->clean_on_exit_handler(process);
44+
}
45+
}
46+
3447
kill(p->pid, sig);
3548
if (!in_signal)
3649
free(p);
@@ -49,10 +62,11 @@ static void cleanup_children_on_exit(void)
4962
cleanup_children(SIGTERM, 0);
5063
}
5164

52-
static void mark_child_for_cleanup(pid_t pid)
65+
static void mark_child_for_cleanup(pid_t pid, struct child_process *process)
5366
{
5467
struct child_to_clean *p = xmalloc(sizeof(*p));
5568
p->pid = pid;
69+
p->process = process;
5670
p->next = children_to_clean;
5771
children_to_clean = p;
5872

@@ -422,7 +436,7 @@ int start_command(struct child_process *cmd)
422436
if (cmd->pid < 0)
423437
error_errno("cannot fork() for %s", cmd->argv[0]);
424438
else if (cmd->clean_on_exit)
425-
mark_child_for_cleanup(cmd->pid);
439+
mark_child_for_cleanup(cmd->pid, cmd);
426440

427441
/*
428442
* Wait for child's execvp. If the execvp succeeds (or if fork()
@@ -483,7 +497,7 @@ int start_command(struct child_process *cmd)
483497
if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
484498
error_errno("cannot spawn %s", cmd->argv[0]);
485499
if (cmd->clean_on_exit && cmd->pid >= 0)
486-
mark_child_for_cleanup(cmd->pid);
500+
mark_child_for_cleanup(cmd->pid, cmd);
487501

488502
argv_array_clear(&nargv);
489503
cmd->argv = sargv;
@@ -765,7 +779,7 @@ int start_async(struct async *async)
765779
exit(!!async->proc(proc_in, proc_out, async->data));
766780
}
767781

768-
mark_child_for_cleanup(async->pid);
782+
mark_child_for_cleanup(async->pid, NULL);
769783

770784
if (need_in)
771785
close(fdin[0]);

run-command.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct child_process {
4343
unsigned stdout_to_stderr:1;
4444
unsigned use_shell:1;
4545
unsigned clean_on_exit:1;
46+
void (*clean_on_exit_handler)(struct child_process *process);
47+
void *clean_on_exit_handler_cbdata;
4648
};
4749

4850
#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }

0 commit comments

Comments
 (0)