1
1
#include "cache.h"
2
2
#include "run-command.h"
3
3
#include "exec_cmd.h"
4
+ #include "sigchain.h"
4
5
#include "argv-array.h"
5
6
7
+ struct child_to_clean {
8
+ pid_t pid ;
9
+ struct child_to_clean * next ;
10
+ };
11
+ static struct child_to_clean * children_to_clean ;
12
+ static int installed_child_cleanup_handler ;
13
+
14
+ static void cleanup_children (int sig )
15
+ {
16
+ while (children_to_clean ) {
17
+ struct child_to_clean * p = children_to_clean ;
18
+ children_to_clean = p -> next ;
19
+ kill (p -> pid , sig );
20
+ free (p );
21
+ }
22
+ }
23
+
24
+ static void cleanup_children_on_signal (int sig )
25
+ {
26
+ cleanup_children (sig );
27
+ sigchain_pop (sig );
28
+ raise (sig );
29
+ }
30
+
31
+ static void cleanup_children_on_exit (void )
32
+ {
33
+ cleanup_children (SIGTERM );
34
+ }
35
+
36
+ static void mark_child_for_cleanup (pid_t pid )
37
+ {
38
+ struct child_to_clean * p = xmalloc (sizeof (* p ));
39
+ p -> pid = pid ;
40
+ p -> next = children_to_clean ;
41
+ children_to_clean = p ;
42
+
43
+ if (!installed_child_cleanup_handler ) {
44
+ atexit (cleanup_children_on_exit );
45
+ sigchain_push_common (cleanup_children_on_signal );
46
+ installed_child_cleanup_handler = 1 ;
47
+ }
48
+ }
49
+
50
+ static void clear_child_for_cleanup (pid_t pid )
51
+ {
52
+ struct child_to_clean * * last , * p ;
53
+
54
+ last = & children_to_clean ;
55
+ for (p = children_to_clean ; p ; p = p -> next ) {
56
+ if (p -> pid == pid ) {
57
+ * last = p -> next ;
58
+ free (p );
59
+ return ;
60
+ }
61
+ }
62
+ }
63
+
6
64
static inline void close_pair (int fd [2 ])
7
65
{
8
66
close (fd [0 ]);
@@ -130,6 +188,9 @@ static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
130
188
} else {
131
189
error ("waitpid is confused (%s)" , argv0 );
132
190
}
191
+
192
+ clear_child_for_cleanup (pid );
193
+
133
194
errno = failed_errno ;
134
195
return code ;
135
196
}
@@ -292,6 +353,8 @@ int start_command(struct child_process *cmd)
292
353
if (cmd -> pid < 0 )
293
354
error ("cannot fork() for %s: %s" , cmd -> argv [0 ],
294
355
strerror (failed_errno = errno ));
356
+ else if (cmd -> clean_on_exit )
357
+ mark_child_for_cleanup (cmd -> pid );
295
358
296
359
/*
297
360
* Wait for child's execvp. If the execvp succeeds (or if fork()
@@ -312,6 +375,7 @@ int start_command(struct child_process *cmd)
312
375
cmd -> pid = -1 ;
313
376
}
314
377
close (notify_pipe [0 ]);
378
+
315
379
}
316
380
#else
317
381
{
@@ -356,6 +420,8 @@ int start_command(struct child_process *cmd)
356
420
failed_errno = errno ;
357
421
if (cmd -> pid < 0 && (!cmd -> silent_exec_failure || errno != ENOENT ))
358
422
error ("cannot spawn %s: %s" , cmd -> argv [0 ], strerror (errno ));
423
+ if (cmd -> clean_on_exit && cmd -> pid >= 0 )
424
+ mark_child_for_cleanup (cmd -> pid );
359
425
360
426
if (cmd -> env )
361
427
free_environ (env );
@@ -431,6 +497,7 @@ static void prepare_run_command_v_opt(struct child_process *cmd,
431
497
cmd -> stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0 ;
432
498
cmd -> silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0 ;
433
499
cmd -> use_shell = opt & RUN_USING_SHELL ? 1 : 0 ;
500
+ cmd -> clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0 ;
434
501
}
435
502
436
503
int run_command_v_opt (const char * * argv , int opt )
@@ -540,6 +607,8 @@ int start_async(struct async *async)
540
607
exit (!!async -> proc (proc_in , proc_out , async -> data ));
541
608
}
542
609
610
+ mark_child_for_cleanup (async -> pid );
611
+
543
612
if (need_in )
544
613
close (fdin [0 ]);
545
614
else if (async -> in )
0 commit comments