File: | run-command.c |
Location: | line 51, column 7 |
Description: | Access to field 'wait_after_clean' results in a dereference of a null pointer (loaded from field 'process') |
1 | #include "cache.h" | |||
2 | #include "run-command.h" | |||
3 | #include "exec_cmd.h" | |||
4 | #include "sigchain.h" | |||
5 | #include "argv-array.h" | |||
6 | #include "thread-utils.h" | |||
7 | #include "strbuf.h" | |||
8 | ||||
9 | void child_process_init(struct child_process *child) | |||
10 | { | |||
11 | memset(child, 0, sizeof(*child))__builtin___memset_chk (child, 0, sizeof(*child), __builtin_object_size (child, 0)); | |||
12 | argv_array_init(&child->args); | |||
13 | argv_array_init(&child->env_array); | |||
14 | } | |||
15 | ||||
16 | void child_process_clear(struct child_process *child) | |||
17 | { | |||
18 | argv_array_clear(&child->args); | |||
19 | argv_array_clear(&child->env_array); | |||
20 | } | |||
21 | ||||
22 | struct child_to_clean { | |||
23 | pid_t pid; | |||
24 | struct child_process *process; | |||
25 | struct child_to_clean *next; | |||
26 | }; | |||
27 | static struct child_to_clean *children_to_clean; | |||
28 | static int installed_child_cleanup_handler; | |||
29 | ||||
30 | static void cleanup_children(int sig, int in_signal) | |||
31 | { | |||
32 | struct child_to_clean *children_to_wait_for = NULL((void*)0); | |||
33 | ||||
34 | while (children_to_clean) { | |||
35 | struct child_to_clean *p = children_to_clean; | |||
36 | children_to_clean = p->next; | |||
37 | ||||
38 | if (p->process && !in_signal) { | |||
39 | struct child_process *process = p->process; | |||
40 | if (process->clean_on_exit_handler) { | |||
41 | trace_printf(trace_printf_key_fl("run-command.c", 44, ((void*)0), "trace: run_command: running exit handler for pid %" "j" "u", (uintmax_t)p->pid) | |||
42 | "trace: run_command: running exit handler for pid %"trace_printf_key_fl("run-command.c", 44, ((void*)0), "trace: run_command: running exit handler for pid %" "j" "u", (uintmax_t)p->pid) | |||
43 | PRIuMAX, (uintmax_t)p->pidtrace_printf_key_fl("run-command.c", 44, ((void*)0), "trace: run_command: running exit handler for pid %" "j" "u", (uintmax_t)p->pid) | |||
44 | )trace_printf_key_fl("run-command.c", 44, ((void*)0), "trace: run_command: running exit handler for pid %" "j" "u", (uintmax_t)p->pid); | |||
45 | process->clean_on_exit_handler(process); | |||
46 | } | |||
47 | } | |||
48 | ||||
49 | kill(p->pid, sig); | |||
50 | ||||
51 | if (p->process->wait_after_clean) { | |||
| ||||
52 | p->next = children_to_wait_for; | |||
53 | children_to_wait_for = p; | |||
54 | } else { | |||
55 | if (!in_signal) | |||
56 | free(p); | |||
57 | } | |||
58 | } | |||
59 | ||||
60 | while (children_to_wait_for) { | |||
61 | struct child_to_clean *p = children_to_wait_for; | |||
62 | children_to_wait_for = p->next; | |||
63 | ||||
64 | while (waitpid(p->pid, NULL((void*)0), 0) < 0 && errno(*__error()) == EINTR4) | |||
65 | ; /* spin waiting for process exit or error */ | |||
66 | ||||
67 | if (!in_signal) | |||
68 | free(p); | |||
69 | } | |||
70 | } | |||
71 | ||||
72 | static void cleanup_children_on_signal(int sig) | |||
73 | { | |||
74 | cleanup_children(sig, 1); | |||
75 | sigchain_pop(sig); | |||
76 | raise(sig); | |||
77 | } | |||
78 | ||||
79 | static void cleanup_children_on_exit(void) | |||
80 | { | |||
81 | cleanup_children(SIGTERM15, 0); | |||
| ||||
82 | } | |||
83 | ||||
84 | static void mark_child_for_cleanup(pid_t pid, struct child_process *process) | |||
85 | { | |||
86 | struct child_to_clean *p = xmalloc(sizeof(*p)); | |||
87 | p->pid = pid; | |||
88 | p->process = process; | |||
89 | p->next = children_to_clean; | |||
90 | children_to_clean = p; | |||
91 | ||||
92 | if (!installed_child_cleanup_handler) { | |||
93 | atexit(cleanup_children_on_exit); | |||
94 | sigchain_push_common(cleanup_children_on_signal); | |||
95 | installed_child_cleanup_handler = 1; | |||
96 | } | |||
97 | } | |||
98 | ||||
99 | static void clear_child_for_cleanup(pid_t pid) | |||
100 | { | |||
101 | struct child_to_clean **pp; | |||
102 | ||||
103 | for (pp = &children_to_clean; *pp; pp = &(*pp)->next) { | |||
104 | struct child_to_clean *clean_me = *pp; | |||
105 | ||||
106 | if (clean_me->pid == pid) { | |||
107 | *pp = clean_me->next; | |||
108 | free(clean_me); | |||
109 | return; | |||
110 | } | |||
111 | } | |||
112 | } | |||
113 | ||||
114 | static inline void close_pair(int fd[2]) | |||
115 | { | |||
116 | close(fd[0]); | |||
117 | close(fd[1]); | |||
118 | } | |||
119 | ||||
120 | #ifndef GIT_WINDOWS_NATIVE | |||
121 | static inline void dup_devnull(int to) | |||
122 | { | |||
123 | int fd = open("/dev/null", O_RDWR0x0002); | |||
124 | if (fd < 0) | |||
125 | die_errno(_("open /dev/null failed")); | |||
126 | if (dup2(fd, to) < 0) | |||
127 | die_errno(_("dup2(%d,%d) failed"), fd, to); | |||
128 | close(fd); | |||
129 | } | |||
130 | #endif | |||
131 | ||||
132 | static char *locate_in_PATH(const char *file) | |||
133 | { | |||
134 | const char *p = getenv("PATH"); | |||
135 | struct strbuf buf = STRBUF_INIT{ 0, 0, strbuf_slopbuf }; | |||
136 | ||||
137 | if (!p || !*p) | |||
138 | return NULL((void*)0); | |||
139 | ||||
140 | while (1) { | |||
141 | const char *end = strchrnulgitstrchrnul(p, ':'); | |||
142 | ||||
143 | strbuf_reset(&buf)strbuf_setlen(&buf, 0); | |||
144 | ||||
145 | /* POSIX specifies an empty entry as the current directory. */ | |||
146 | if (end != p) { | |||
147 | strbuf_add(&buf, p, end - p); | |||
148 | strbuf_addch(&buf, '/'); | |||
149 | } | |||
150 | strbuf_addstr(&buf, file); | |||
151 | ||||
152 | if (!access(buf.buf, F_OK0)) | |||
153 | return strbuf_detach(&buf, NULL((void*)0)); | |||
154 | ||||
155 | if (!*end) | |||
156 | break; | |||
157 | p = end + 1; | |||
158 | } | |||
159 | ||||
160 | strbuf_release(&buf); | |||
161 | return NULL((void*)0); | |||
162 | } | |||
163 | ||||
164 | static int exists_in_PATH(const char *file) | |||
165 | { | |||
166 | char *r = locate_in_PATH(file); | |||
167 | free(r); | |||
168 | return r != NULL((void*)0); | |||
169 | } | |||
170 | ||||
171 | int sane_execvp(const char *file, char * const argv[]) | |||
172 | { | |||
173 | if (!execvp(file, argv)) | |||
174 | return 0; /* cannot happen ;-) */ | |||
175 | ||||
176 | /* | |||
177 | * When a command can't be found because one of the directories | |||
178 | * listed in $PATH is unsearchable, execvp reports EACCES, but | |||
179 | * careful usability testing (read: analysis of occasional bug | |||
180 | * reports) reveals that "No such file or directory" is more | |||
181 | * intuitive. | |||
182 | * | |||
183 | * We avoid commands with "/", because execvp will not do $PATH | |||
184 | * lookups in that case. | |||
185 | * | |||
186 | * The reassignment of EACCES to errno looks like a no-op below, | |||
187 | * but we need to protect against exists_in_PATH overwriting errno. | |||
188 | */ | |||
189 | if (errno(*__error()) == EACCES13 && !strchr(file, '/')) | |||
190 | errno(*__error()) = exists_in_PATH(file) ? EACCES13 : ENOENT2; | |||
191 | else if (errno(*__error()) == ENOTDIR20 && !strchr(file, '/')) | |||
192 | errno(*__error()) = ENOENT2; | |||
193 | return -1; | |||
194 | } | |||
195 | ||||
196 | static const char **prepare_shell_cmd(struct argv_array *out, const char **argv) | |||
197 | { | |||
198 | if (!argv[0]) | |||
199 | die("BUG: shell command is empty"); | |||
200 | ||||
201 | if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) { | |||
202 | #ifndef GIT_WINDOWS_NATIVE | |||
203 | argv_array_push(out, SHELL_PATH"/bin/sh"); | |||
204 | #else | |||
205 | argv_array_push(out, "sh"); | |||
206 | #endif | |||
207 | argv_array_push(out, "-c"); | |||
208 | ||||
209 | /* | |||
210 | * If we have no extra arguments, we do not even need to | |||
211 | * bother with the "$@" magic. | |||
212 | */ | |||
213 | if (!argv[1]) | |||
214 | argv_array_push(out, argv[0]); | |||
215 | else | |||
216 | argv_array_pushf(out, "%s \"$@\"", argv[0]); | |||
217 | } | |||
218 | ||||
219 | argv_array_pushv(out, argv); | |||
220 | return out->argv; | |||
221 | } | |||
222 | ||||
223 | #ifndef GIT_WINDOWS_NATIVE | |||
224 | static int execv_shell_cmd(const char **argv) | |||
225 | { | |||
226 | struct argv_array nargv = ARGV_ARRAY_INIT{ empty_argv, 0, 0 }; | |||
227 | prepare_shell_cmd(&nargv, argv); | |||
228 | trace_argv_printf(nargv.argv, "trace: exec:")trace_argv_printf_fl("run-command.c", 228, nargv.argv, "trace: exec:" ); | |||
229 | sane_execvp(nargv.argv[0], (char **)nargv.argv); | |||
230 | argv_array_clear(&nargv); | |||
231 | return -1; | |||
232 | } | |||
233 | #endif | |||
234 | ||||
235 | #ifndef GIT_WINDOWS_NATIVE | |||
236 | static int child_notifier = -1; | |||
237 | ||||
238 | static void notify_parent(void) | |||
239 | { | |||
240 | /* | |||
241 | * execvp failed. If possible, we'd like to let start_command | |||
242 | * know, so failures like ENOENT can be handled right away; but | |||
243 | * otherwise, finish_command will still report the error. | |||
244 | */ | |||
245 | xwrite(child_notifier, "", 1); | |||
246 | } | |||
247 | #endif | |||
248 | ||||
249 | static inline void set_cloexec(int fd) | |||
250 | { | |||
251 | int flags = fcntl(fd, F_GETFD1); | |||
252 | if (flags >= 0) | |||
253 | fcntl(fd, F_SETFD2, flags | FD_CLOEXEC1); | |||
254 | } | |||
255 | ||||
256 | static int wait_or_whine(pid_t pid, const char *argv0, int in_signal) | |||
257 | { | |||
258 | int status, code = -1; | |||
259 | pid_t waiting; | |||
260 | int failed_errno = 0; | |||
261 | ||||
262 | while ((waiting = waitpid(pid, &status, 0)) < 0 && errno(*__error()) == EINTR4) | |||
263 | ; /* nothing */ | |||
264 | if (in_signal) | |||
265 | return 0; | |||
266 | ||||
267 | if (waiting < 0) { | |||
268 | failed_errno = errno(*__error()); | |||
269 | error_errno("waitpid for %s failed", argv0)(error_errno("waitpid for %s failed", argv0), const_error()); | |||
270 | } else if (waiting != pid) { | |||
271 | error("waitpid is confused (%s)", argv0)(error("waitpid is confused (%s)", argv0), const_error()); | |||
272 | } else if (WIFSIGNALED(status)(((*(int *)&(status)) & 0177) != 0177 && ((*( int *)&(status)) & 0177) != 0)) { | |||
273 | code = WTERMSIG(status)(((*(int *)&(status)) & 0177)); | |||
274 | if (code != SIGINT2 && code != SIGQUIT3 && code != SIGPIPE13) | |||
275 | error("%s died of signal %d", argv0, code)(error("%s died of signal %d", argv0, code), const_error()); | |||
276 | /* | |||
277 | * This return value is chosen so that code & 0xff | |||
278 | * mimics the exit code that a POSIX shell would report for | |||
279 | * a program that died from this signal. | |||
280 | */ | |||
281 | code += 128; | |||
282 | } else if (WIFEXITED(status)(((*(int *)&(status)) & 0177) == 0)) { | |||
283 | code = WEXITSTATUS(status)(((*(int *)&(status)) >> 8) & 0x000000ff); | |||
284 | /* | |||
285 | * Convert special exit code when execvp failed. | |||
286 | */ | |||
287 | if (code == 127) { | |||
288 | code = -1; | |||
289 | failed_errno = ENOENT2; | |||
290 | } | |||
291 | } else { | |||
292 | error("waitpid is confused (%s)", argv0)(error("waitpid is confused (%s)", argv0), const_error()); | |||
293 | } | |||
294 | ||||
295 | clear_child_for_cleanup(pid); | |||
296 | ||||
297 | errno(*__error()) = failed_errno; | |||
298 | return code; | |||
299 | } | |||
300 | ||||
301 | int start_command(struct child_process *cmd) | |||
302 | { | |||
303 | int need_in, need_out, need_err; | |||
304 | int fdin[2], fdout[2], fderr[2]; | |||
305 | int failed_errno; | |||
306 | char *str; | |||
307 | ||||
308 | if (!cmd->argv) | |||
309 | cmd->argv = cmd->args.argv; | |||
310 | if (!cmd->env) | |||
311 | cmd->env = cmd->env_array.argv; | |||
312 | ||||
313 | /* | |||
314 | * In case of errors we must keep the promise to close FDs | |||
315 | * that have been passed in via ->in and ->out. | |||
316 | */ | |||
317 | ||||
318 | need_in = !cmd->no_stdin && cmd->in < 0; | |||
319 | if (need_in) { | |||
320 | if (pipe(fdin) < 0) { | |||
321 | failed_errno = errno(*__error()); | |||
322 | if (cmd->out > 0) | |||
323 | close(cmd->out); | |||
324 | str = "standard input"; | |||
325 | goto fail_pipe; | |||
326 | } | |||
327 | cmd->in = fdin[1]; | |||
328 | } | |||
329 | ||||
330 | need_out = !cmd->no_stdout | |||
331 | && !cmd->stdout_to_stderr | |||
332 | && cmd->out < 0; | |||
333 | if (need_out) { | |||
334 | if (pipe(fdout) < 0) { | |||
335 | failed_errno = errno(*__error()); | |||
336 | if (need_in) | |||
337 | close_pair(fdin); | |||
338 | else if (cmd->in) | |||
339 | close(cmd->in); | |||
340 | str = "standard output"; | |||
341 | goto fail_pipe; | |||
342 | } | |||
343 | cmd->out = fdout[0]; | |||
344 | } | |||
345 | ||||
346 | need_err = !cmd->no_stderr && cmd->err < 0; | |||
347 | if (need_err) { | |||
348 | if (pipe(fderr) < 0) { | |||
349 | failed_errno = errno(*__error()); | |||
350 | if (need_in) | |||
351 | close_pair(fdin); | |||
352 | else if (cmd->in) | |||
353 | close(cmd->in); | |||
354 | if (need_out) | |||
355 | close_pair(fdout); | |||
356 | else if (cmd->out) | |||
357 | close(cmd->out); | |||
358 | str = "standard error"; | |||
359 | fail_pipe: | |||
360 | error("cannot create %s pipe for %s: %s",(error("cannot create %s pipe for %s: %s", str, cmd->argv[ 0], strerror(failed_errno)), const_error()) | |||
361 | str, cmd->argv[0], strerror(failed_errno))(error("cannot create %s pipe for %s: %s", str, cmd->argv[ 0], strerror(failed_errno)), const_error()); | |||
362 | child_process_clear(cmd); | |||
363 | errno(*__error()) = failed_errno; | |||
364 | return -1; | |||
365 | } | |||
366 | cmd->err = fderr[0]; | |||
367 | } | |||
368 | ||||
369 | trace_argv_printf(cmd->argv, "trace: run_command:")trace_argv_printf_fl("run-command.c", 369, cmd->argv, "trace: run_command:" ); | |||
370 | fflush(NULL((void*)0)); | |||
371 | ||||
372 | #ifndef GIT_WINDOWS_NATIVE | |||
373 | { | |||
374 | int notify_pipe[2]; | |||
375 | if (pipe(notify_pipe)) | |||
376 | notify_pipe[0] = notify_pipe[1] = -1; | |||
377 | ||||
378 | cmd->pid = fork(); | |||
379 | failed_errno = errno(*__error()); | |||
380 | if (!cmd->pid) { | |||
381 | /* | |||
382 | * Redirect the channel to write syscall error messages to | |||
383 | * before redirecting the process's stderr so that all die() | |||
384 | * in subsequent call paths use the parent's stderr. | |||
385 | */ | |||
386 | if (cmd->no_stderr || need_err) { | |||
387 | int child_err = dup(2); | |||
388 | set_cloexec(child_err); | |||
389 | set_error_handle(fdopen(child_err, "w")); | |||
390 | } | |||
391 | ||||
392 | close(notify_pipe[0]); | |||
393 | set_cloexec(notify_pipe[1]); | |||
394 | child_notifier = notify_pipe[1]; | |||
395 | atexit(notify_parent); | |||
396 | ||||
397 | if (cmd->no_stdin) | |||
398 | dup_devnull(0); | |||
399 | else if (need_in) { | |||
400 | dup2(fdin[0], 0); | |||
401 | close_pair(fdin); | |||
402 | } else if (cmd->in) { | |||
403 | dup2(cmd->in, 0); | |||
404 | close(cmd->in); | |||
405 | } | |||
406 | ||||
407 | if (cmd->no_stderr) | |||
408 | dup_devnull(2); | |||
409 | else if (need_err) { | |||
410 | dup2(fderr[1], 2); | |||
411 | close_pair(fderr); | |||
412 | } else if (cmd->err > 1) { | |||
413 | dup2(cmd->err, 2); | |||
414 | close(cmd->err); | |||
415 | } | |||
416 | ||||
417 | if (cmd->no_stdout) | |||
418 | dup_devnull(1); | |||
419 | else if (cmd->stdout_to_stderr) | |||
420 | dup2(2, 1); | |||
421 | else if (need_out) { | |||
422 | dup2(fdout[1], 1); | |||
423 | close_pair(fdout); | |||
424 | } else if (cmd->out > 1) { | |||
425 | dup2(cmd->out, 1); | |||
426 | close(cmd->out); | |||
427 | } | |||
428 | ||||
429 | if (cmd->dir && chdir(cmd->dir)) | |||
430 | die_errno("exec '%s': cd to '%s' failed", cmd->argv[0], | |||
431 | cmd->dir); | |||
432 | if (cmd->env) { | |||
433 | for (; *cmd->env; cmd->env++) { | |||
434 | if (strchr(*cmd->env, '=')) | |||
435 | putenv((char *)*cmd->env); | |||
436 | else | |||
437 | unsetenv(*cmd->env); | |||
438 | } | |||
439 | } | |||
440 | if (cmd->git_cmd) | |||
441 | execv_git_cmd(cmd->argv); | |||
442 | else if (cmd->use_shell) | |||
443 | execv_shell_cmd(cmd->argv); | |||
444 | else | |||
445 | sane_execvp(cmd->argv[0], (char *const*) cmd->argv); | |||
446 | if (errno(*__error()) == ENOENT2) { | |||
447 | if (!cmd->silent_exec_failure) | |||
448 | error("cannot run %s: %s", cmd->argv[0],(error("cannot run %s: %s", cmd->argv[0], strerror(2)), const_error ()) | |||
449 | strerror(ENOENT))(error("cannot run %s: %s", cmd->argv[0], strerror(2)), const_error ()); | |||
450 | exit(127); | |||
451 | } else { | |||
452 | die_errno("cannot exec '%s'", cmd->argv[0]); | |||
453 | } | |||
454 | } | |||
455 | if (cmd->pid < 0) | |||
456 | error_errno("cannot fork() for %s", cmd->argv[0])(error_errno("cannot fork() for %s", cmd->argv[0]), const_error ()); | |||
457 | else if (cmd->clean_on_exit) | |||
458 | mark_child_for_cleanup(cmd->pid, cmd); | |||
459 | ||||
460 | /* | |||
461 | * Wait for child's execvp. If the execvp succeeds (or if fork() | |||
462 | * failed), EOF is seen immediately by the parent. Otherwise, the | |||
463 | * child process sends a single byte. | |||
464 | * Note that use of this infrastructure is completely advisory, | |||
465 | * therefore, we keep error checks minimal. | |||
466 | */ | |||
467 | close(notify_pipe[1]); | |||
468 | if (read(notify_pipe[0], ¬ify_pipe[1], 1) == 1) { | |||
469 | /* | |||
470 | * At this point we know that fork() succeeded, but execvp() | |||
471 | * failed. Errors have been reported to our stderr. | |||
472 | */ | |||
473 | wait_or_whine(cmd->pid, cmd->argv[0], 0); | |||
474 | failed_errno = errno(*__error()); | |||
475 | cmd->pid = -1; | |||
476 | } | |||
477 | close(notify_pipe[0]); | |||
478 | } | |||
479 | #else | |||
480 | { | |||
481 | int fhin = 0, fhout = 1, fherr = 2; | |||
482 | const char **sargv = cmd->argv; | |||
483 | struct argv_array nargv = ARGV_ARRAY_INIT{ empty_argv, 0, 0 }; | |||
484 | ||||
485 | if (cmd->no_stdin) | |||
486 | fhin = open("/dev/null", O_RDWR0x0002); | |||
487 | else if (need_in) | |||
488 | fhin = dup(fdin[0]); | |||
489 | else if (cmd->in) | |||
490 | fhin = dup(cmd->in); | |||
491 | ||||
492 | if (cmd->no_stderr) | |||
493 | fherr = open("/dev/null", O_RDWR0x0002); | |||
494 | else if (need_err) | |||
495 | fherr = dup(fderr[1]); | |||
496 | else if (cmd->err > 2) | |||
497 | fherr = dup(cmd->err); | |||
498 | ||||
499 | if (cmd->no_stdout) | |||
500 | fhout = open("/dev/null", O_RDWR0x0002); | |||
501 | else if (cmd->stdout_to_stderr) | |||
502 | fhout = dup(fherr); | |||
503 | else if (need_out) | |||
504 | fhout = dup(fdout[1]); | |||
505 | else if (cmd->out > 1) | |||
506 | fhout = dup(cmd->out); | |||
507 | ||||
508 | if (cmd->git_cmd) | |||
509 | cmd->argv = prepare_git_cmd(&nargv, cmd->argv); | |||
510 | else if (cmd->use_shell) | |||
511 | cmd->argv = prepare_shell_cmd(&nargv, cmd->argv); | |||
512 | ||||
513 | cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env, | |||
514 | cmd->dir, fhin, fhout, fherr); | |||
515 | failed_errno = errno(*__error()); | |||
516 | if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno(*__error()) != ENOENT2)) | |||
517 | error_errno("cannot spawn %s", cmd->argv[0])(error_errno("cannot spawn %s", cmd->argv[0]), const_error ()); | |||
518 | if (cmd->clean_on_exit && cmd->pid >= 0) | |||
519 | mark_child_for_cleanup(cmd->pid, cmd); | |||
520 | ||||
521 | argv_array_clear(&nargv); | |||
522 | cmd->argv = sargv; | |||
523 | if (fhin != 0) | |||
524 | close(fhin); | |||
525 | if (fhout != 1) | |||
526 | close(fhout); | |||
527 | if (fherr != 2) | |||
528 | close(fherr); | |||
529 | } | |||
530 | #endif | |||
531 | ||||
532 | if (cmd->pid < 0) { | |||
533 | if (need_in) | |||
534 | close_pair(fdin); | |||
535 | else if (cmd->in) | |||
536 | close(cmd->in); | |||
537 | if (need_out) | |||
538 | close_pair(fdout); | |||
539 | else if (cmd->out) | |||
540 | close(cmd->out); | |||
541 | if (need_err) | |||
542 | close_pair(fderr); | |||
543 | else if (cmd->err) | |||
544 | close(cmd->err); | |||
545 | child_process_clear(cmd); | |||
546 | errno(*__error()) = failed_errno; | |||
547 | return -1; | |||
548 | } | |||
549 | ||||
550 | if (need_in) | |||
551 | close(fdin[0]); | |||
552 | else if (cmd->in) | |||
553 | close(cmd->in); | |||
554 | ||||
555 | if (need_out) | |||
556 | close(fdout[1]); | |||
557 | else if (cmd->out) | |||
558 | close(cmd->out); | |||
559 | ||||
560 | if (need_err) | |||
561 | close(fderr[1]); | |||
562 | else if (cmd->err) | |||
563 | close(cmd->err); | |||
564 | ||||
565 | return 0; | |||
566 | } | |||
567 | ||||
568 | int finish_command(struct child_process *cmd) | |||
569 | { | |||
570 | int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0); | |||
571 | child_process_clear(cmd); | |||
572 | return ret; | |||
573 | } | |||
574 | ||||
575 | int finish_command_in_signal(struct child_process *cmd) | |||
576 | { | |||
577 | return wait_or_whine(cmd->pid, cmd->argv[0], 1); | |||
578 | } | |||
579 | ||||
580 | ||||
581 | int run_command(struct child_process *cmd) | |||
582 | { | |||
583 | int code; | |||
584 | ||||
585 | if (cmd->out < 0 || cmd->err < 0) | |||
586 | die("BUG: run_command with a pipe can cause deadlock"); | |||
587 | ||||
588 | code = start_command(cmd); | |||
589 | if (code) | |||
590 | return code; | |||
591 | return finish_command(cmd); | |||
592 | } | |||
593 | ||||
594 | int run_command_v_opt(const char **argv, int opt) | |||
595 | { | |||
596 | return run_command_v_opt_cd_env(argv, opt, NULL((void*)0), NULL((void*)0)); | |||
597 | } | |||
598 | ||||
599 | int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env) | |||
600 | { | |||
601 | struct child_process cmd = CHILD_PROCESS_INIT{ ((void*)0), { empty_argv, 0, 0 }, { empty_argv, 0, 0 } }; | |||
602 | cmd.argv = argv; | |||
603 | cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN1 ? 1 : 0; | |||
604 | cmd.git_cmd = opt & RUN_GIT_CMD2 ? 1 : 0; | |||
605 | cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR4 ? 1 : 0; | |||
606 | cmd.silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE8 ? 1 : 0; | |||
607 | cmd.use_shell = opt & RUN_USING_SHELL16 ? 1 : 0; | |||
608 | cmd.clean_on_exit = opt & RUN_CLEAN_ON_EXIT32 ? 1 : 0; | |||
609 | cmd.dir = dir; | |||
610 | cmd.env = env; | |||
611 | return run_command(&cmd); | |||
612 | } | |||
613 | ||||
614 | #ifndef NO_PTHREADS | |||
615 | static pthread_t main_thread; | |||
616 | static int main_thread_set; | |||
617 | static pthread_key_t async_key; | |||
618 | static pthread_key_t async_die_counter; | |||
619 | ||||
620 | static void *run_thread(void *data) | |||
621 | { | |||
622 | struct async *async = data; | |||
623 | intptr_t ret; | |||
624 | ||||
625 | if (async->isolate_sigpipe) { | |||
626 | sigset_t mask; | |||
627 | sigemptyset(&mask)(*(&mask) = 0, 0); | |||
628 | sigaddset(&mask, SIGPIPE)(*(&mask) |= __sigbits(13), 0); | |||
629 | if (pthread_sigmask(SIG_BLOCK1, &mask, NULL((void*)0)) < 0) { | |||
630 | ret = error("unable to block SIGPIPE in async thread")(error("unable to block SIGPIPE in async thread"), const_error ()); | |||
631 | return (void *)ret; | |||
632 | } | |||
633 | } | |||
634 | ||||
635 | pthread_setspecific(async_key, async); | |||
636 | ret = async->proc(async->proc_in, async->proc_out, async->data); | |||
637 | return (void *)ret; | |||
638 | } | |||
639 | ||||
640 | static NORETURN__attribute__((__noreturn__)) void die_async(const char *err, va_list params) | |||
641 | { | |||
642 | vreportf("fatal: ", err, params); | |||
643 | ||||
644 | if (in_async()) { | |||
645 | struct async *async = pthread_getspecific(async_key); | |||
646 | if (async->proc_in >= 0) | |||
647 | close(async->proc_in); | |||
648 | if (async->proc_out >= 0) | |||
649 | close(async->proc_out); | |||
650 | pthread_exit((void *)128); | |||
651 | } | |||
652 | ||||
653 | exit(128); | |||
654 | } | |||
655 | ||||
656 | static int async_die_is_recursing(void) | |||
657 | { | |||
658 | void *ret = pthread_getspecific(async_die_counter); | |||
659 | pthread_setspecific(async_die_counter, (void *)1); | |||
660 | return ret != NULL((void*)0); | |||
661 | } | |||
662 | ||||
663 | int in_async(void) | |||
664 | { | |||
665 | if (!main_thread_set) | |||
666 | return 0; /* no asyncs started yet */ | |||
667 | return !pthread_equal(main_thread, pthread_self()); | |||
668 | } | |||
669 | ||||
670 | static void NORETURN__attribute__((__noreturn__)) async_exit(int code) | |||
671 | { | |||
672 | pthread_exit((void *)(intptr_t)code); | |||
673 | } | |||
674 | ||||
675 | #else | |||
676 | ||||
677 | static struct { | |||
678 | void (**handlers)(void); | |||
679 | size_t nr; | |||
680 | size_t alloc; | |||
681 | } git_atexit_hdlrs; | |||
682 | ||||
683 | static int git_atexit_installed; | |||
684 | ||||
685 | static void git_atexit_dispatch(void) | |||
686 | { | |||
687 | size_t i; | |||
688 | ||||
689 | for (i=git_atexit_hdlrs.nr ; i ; i--) | |||
690 | git_atexit_hdlrs.handlers[i-1](); | |||
691 | } | |||
692 | ||||
693 | static void git_atexit_clear(void) | |||
694 | { | |||
695 | free(git_atexit_hdlrs.handlers); | |||
696 | memset(&git_atexit_hdlrs, 0, sizeof(git_atexit_hdlrs))__builtin___memset_chk (&git_atexit_hdlrs, 0, sizeof(git_atexit_hdlrs ), __builtin_object_size (&git_atexit_hdlrs, 0)); | |||
697 | git_atexit_installed = 0; | |||
698 | } | |||
699 | ||||
700 | #undef atexit | |||
701 | int git_atexit(void (*handler)(void)) | |||
702 | { | |||
703 | ALLOC_GROW(git_atexit_hdlrs.handlers, git_atexit_hdlrs.nr + 1, git_atexit_hdlrs.alloc)do { if ((git_atexit_hdlrs.nr + 1) > git_atexit_hdlrs.alloc ) { if ((((git_atexit_hdlrs.alloc)+16)*3/2) < (git_atexit_hdlrs .nr + 1)) git_atexit_hdlrs.alloc = (git_atexit_hdlrs.nr + 1); else git_atexit_hdlrs.alloc = (((git_atexit_hdlrs.alloc)+16) *3/2); (git_atexit_hdlrs.handlers) = xrealloc((git_atexit_hdlrs .handlers), st_mult(sizeof(*(git_atexit_hdlrs.handlers)), (git_atexit_hdlrs .alloc))); } } while (0); | |||
704 | git_atexit_hdlrs.handlers[git_atexit_hdlrs.nr++] = handler; | |||
705 | if (!git_atexit_installed) { | |||
706 | if (atexit(&git_atexit_dispatch)) | |||
707 | return -1; | |||
708 | git_atexit_installed = 1; | |||
709 | } | |||
710 | return 0; | |||
711 | } | |||
712 | #define atexit git_atexit | |||
713 | ||||
714 | static int process_is_async; | |||
715 | int in_async(void) | |||
716 | { | |||
717 | return process_is_async; | |||
718 | } | |||
719 | ||||
720 | static void NORETURN__attribute__((__noreturn__)) async_exit(int code) | |||
721 | { | |||
722 | exit(code); | |||
723 | } | |||
724 | ||||
725 | #endif | |||
726 | ||||
727 | void check_pipe(int err) | |||
728 | { | |||
729 | if (err == EPIPE32) { | |||
730 | if (in_async()) | |||
731 | async_exit(141); | |||
732 | ||||
733 | signal(SIGPIPE13, SIG_DFL(void (*)(int))0); | |||
734 | raise(SIGPIPE13); | |||
735 | /* Should never happen, but just in case... */ | |||
736 | exit(141); | |||
737 | } | |||
738 | } | |||
739 | ||||
740 | int start_async(struct async *async) | |||
741 | { | |||
742 | int need_in, need_out; | |||
743 | int fdin[2], fdout[2]; | |||
744 | int proc_in, proc_out; | |||
745 | ||||
746 | need_in = async->in < 0; | |||
747 | if (need_in) { | |||
748 | if (pipe(fdin) < 0) { | |||
749 | if (async->out > 0) | |||
750 | close(async->out); | |||
751 | return error_errno("cannot create pipe")(error_errno("cannot create pipe"), const_error()); | |||
752 | } | |||
753 | async->in = fdin[1]; | |||
754 | } | |||
755 | ||||
756 | need_out = async->out < 0; | |||
757 | if (need_out) { | |||
758 | if (pipe(fdout) < 0) { | |||
759 | if (need_in) | |||
760 | close_pair(fdin); | |||
761 | else if (async->in) | |||
762 | close(async->in); | |||
763 | return error_errno("cannot create pipe")(error_errno("cannot create pipe"), const_error()); | |||
764 | } | |||
765 | async->out = fdout[0]; | |||
766 | } | |||
767 | ||||
768 | if (need_in) | |||
769 | proc_in = fdin[0]; | |||
770 | else if (async->in) | |||
771 | proc_in = async->in; | |||
772 | else | |||
773 | proc_in = -1; | |||
774 | ||||
775 | if (need_out) | |||
776 | proc_out = fdout[1]; | |||
777 | else if (async->out) | |||
778 | proc_out = async->out; | |||
779 | else | |||
780 | proc_out = -1; | |||
781 | ||||
782 | #ifdef NO_PTHREADS | |||
783 | /* Flush stdio before fork() to avoid cloning buffers */ | |||
784 | fflush(NULL((void*)0)); | |||
785 | ||||
786 | async->pid = fork(); | |||
787 | if (async->pid < 0) { | |||
788 | error_errno("fork (async) failed")(error_errno("fork (async) failed"), const_error()); | |||
789 | goto error; | |||
790 | } | |||
791 | if (!async->pid) { | |||
792 | if (need_in) | |||
793 | close(fdin[1]); | |||
794 | if (need_out) | |||
795 | close(fdout[0]); | |||
796 | git_atexit_clear(); | |||
797 | process_is_async = 1; | |||
798 | exit(!!async->proc(proc_in, proc_out, async->data)); | |||
799 | } | |||
800 | ||||
801 | mark_child_for_cleanup(async->pid, NULL((void*)0)); | |||
802 | ||||
803 | if (need_in) | |||
804 | close(fdin[0]); | |||
805 | else if (async->in) | |||
806 | close(async->in); | |||
807 | ||||
808 | if (need_out) | |||
809 | close(fdout[1]); | |||
810 | else if (async->out) | |||
811 | close(async->out); | |||
812 | #else | |||
813 | if (!main_thread_set) { | |||
814 | /* | |||
815 | * We assume that the first time that start_async is called | |||
816 | * it is from the main thread. | |||
817 | */ | |||
818 | main_thread_set = 1; | |||
819 | main_thread = pthread_self(); | |||
820 | pthread_key_create(&async_key, NULL((void*)0)); | |||
821 | pthread_key_create(&async_die_counter, NULL((void*)0)); | |||
822 | set_die_routine(die_async); | |||
823 | set_die_is_recursing_routine(async_die_is_recursing); | |||
824 | } | |||
825 | ||||
826 | if (proc_in >= 0) | |||
827 | set_cloexec(proc_in); | |||
828 | if (proc_out >= 0) | |||
829 | set_cloexec(proc_out); | |||
830 | async->proc_in = proc_in; | |||
831 | async->proc_out = proc_out; | |||
832 | { | |||
833 | int err = pthread_create(&async->tid, NULL((void*)0), run_thread, async); | |||
834 | if (err) { | |||
835 | error_errno("cannot create thread")(error_errno("cannot create thread"), const_error()); | |||
836 | goto error; | |||
837 | } | |||
838 | } | |||
839 | #endif | |||
840 | return 0; | |||
841 | ||||
842 | error: | |||
843 | if (need_in) | |||
844 | close_pair(fdin); | |||
845 | else if (async->in) | |||
846 | close(async->in); | |||
847 | ||||
848 | if (need_out) | |||
849 | close_pair(fdout); | |||
850 | else if (async->out) | |||
851 | close(async->out); | |||
852 | return -1; | |||
853 | } | |||
854 | ||||
855 | int finish_async(struct async *async) | |||
856 | { | |||
857 | #ifdef NO_PTHREADS | |||
858 | return wait_or_whine(async->pid, "child process", 0); | |||
859 | #else | |||
860 | void *ret = (void *)(intptr_t)(-1); | |||
861 | ||||
862 | if (pthread_join(async->tid, &ret)) | |||
863 | error("pthread_join failed")(error("pthread_join failed"), const_error()); | |||
864 | return (int)(intptr_t)ret; | |||
865 | #endif | |||
866 | } | |||
867 | ||||
868 | const char *find_hook(const char *name) | |||
869 | { | |||
870 | static struct strbuf path = STRBUF_INIT{ 0, 0, strbuf_slopbuf }; | |||
871 | ||||
872 | strbuf_reset(&path)strbuf_setlen(&path, 0); | |||
873 | strbuf_git_path(&path, "hooks/%s", name); | |||
874 | if (access(path.buf, X_OK(1<<0)) < 0) { | |||
875 | #ifdef STRIP_EXTENSION | |||
876 | strbuf_addstr(&path, STRIP_EXTENSION); | |||
877 | if (access(path.buf, X_OK(1<<0)) >= 0) | |||
878 | return path.buf; | |||
879 | #endif | |||
880 | return NULL((void*)0); | |||
881 | } | |||
882 | return path.buf; | |||
883 | } | |||
884 | ||||
885 | int run_hook_ve(const char *const *env, const char *name, va_list args) | |||
886 | { | |||
887 | struct child_process hook = CHILD_PROCESS_INIT{ ((void*)0), { empty_argv, 0, 0 }, { empty_argv, 0, 0 } }; | |||
888 | const char *p; | |||
889 | ||||
890 | p = find_hook(name); | |||
891 | if (!p) | |||
892 | return 0; | |||
893 | ||||
894 | argv_array_push(&hook.args, p); | |||
895 | while ((p = va_arg(args, const char *)__builtin_va_arg(args, const char *))) | |||
896 | argv_array_push(&hook.args, p); | |||
897 | hook.env = env; | |||
898 | hook.no_stdin = 1; | |||
899 | hook.stdout_to_stderr = 1; | |||
900 | ||||
901 | return run_command(&hook); | |||
902 | } | |||
903 | ||||
904 | int run_hook_le(const char *const *env, const char *name, ...) | |||
905 | { | |||
906 | va_list args; | |||
907 | int ret; | |||
908 | ||||
909 | va_start(args, name)__builtin_va_start(args, name); | |||
910 | ret = run_hook_ve(env, name, args); | |||
911 | va_end(args)__builtin_va_end(args); | |||
912 | ||||
913 | return ret; | |||
914 | } | |||
915 | ||||
916 | struct io_pump { | |||
917 | /* initialized by caller */ | |||
918 | int fd; | |||
919 | int type; /* POLLOUT or POLLIN */ | |||
920 | union { | |||
921 | struct { | |||
922 | const char *buf; | |||
923 | size_t len; | |||
924 | } out; | |||
925 | struct { | |||
926 | struct strbuf *buf; | |||
927 | size_t hint; | |||
928 | } in; | |||
929 | } u; | |||
930 | ||||
931 | /* returned by pump_io */ | |||
932 | int error; /* 0 for success, otherwise errno */ | |||
933 | ||||
934 | /* internal use */ | |||
935 | struct pollfd *pfd; | |||
936 | }; | |||
937 | ||||
938 | static int pump_io_round(struct io_pump *slots, int nr, struct pollfd *pfd) | |||
939 | { | |||
940 | int pollsize = 0; | |||
941 | int i; | |||
942 | ||||
943 | for (i = 0; i < nr; i++) { | |||
944 | struct io_pump *io = &slots[i]; | |||
945 | if (io->fd < 0) | |||
946 | continue; | |||
947 | pfd[pollsize].fd = io->fd; | |||
948 | pfd[pollsize].events = io->type; | |||
949 | io->pfd = &pfd[pollsize++]; | |||
950 | } | |||
951 | ||||
952 | if (!pollsize) | |||
953 | return 0; | |||
954 | ||||
955 | if (poll(pfd, pollsize, -1) < 0) { | |||
956 | if (errno(*__error()) == EINTR4) | |||
957 | return 1; | |||
958 | die_errno("poll failed"); | |||
959 | } | |||
960 | ||||
961 | for (i = 0; i < nr; i++) { | |||
962 | struct io_pump *io = &slots[i]; | |||
963 | ||||
964 | if (io->fd < 0) | |||
965 | continue; | |||
966 | ||||
967 | if (!(io->pfd->revents & (POLLOUT0x0004|POLLIN0x0001|POLLHUP0x0010|POLLERR0x0008|POLLNVAL0x0020))) | |||
968 | continue; | |||
969 | ||||
970 | if (io->type == POLLOUT0x0004) { | |||
971 | ssize_t len = xwrite(io->fd, | |||
972 | io->u.out.buf, io->u.out.len); | |||
973 | if (len < 0) { | |||
974 | io->error = errno(*__error()); | |||
975 | close(io->fd); | |||
976 | io->fd = -1; | |||
977 | } else { | |||
978 | io->u.out.buf += len; | |||
979 | io->u.out.len -= len; | |||
980 | if (!io->u.out.len) { | |||
981 | close(io->fd); | |||
982 | io->fd = -1; | |||
983 | } | |||
984 | } | |||
985 | } | |||
986 | ||||
987 | if (io->type == POLLIN0x0001) { | |||
988 | ssize_t len = strbuf_read_once(io->u.in.buf, | |||
989 | io->fd, io->u.in.hint); | |||
990 | if (len < 0) | |||
991 | io->error = errno(*__error()); | |||
992 | if (len <= 0) { | |||
993 | close(io->fd); | |||
994 | io->fd = -1; | |||
995 | } | |||
996 | } | |||
997 | } | |||
998 | ||||
999 | return 1; | |||
1000 | } | |||
1001 | ||||
1002 | static int pump_io(struct io_pump *slots, int nr) | |||
1003 | { | |||
1004 | struct pollfd *pfd; | |||
1005 | int i; | |||
1006 | ||||
1007 | for (i = 0; i < nr; i++) | |||
1008 | slots[i].error = 0; | |||
1009 | ||||
1010 | ALLOC_ARRAY(pfd, nr)(pfd) = xmalloc(st_mult(sizeof(*(pfd)), (nr))); | |||
1011 | while (pump_io_round(slots, nr, pfd)) | |||
1012 | ; /* nothing */ | |||
1013 | free(pfd); | |||
1014 | ||||
1015 | /* There may be multiple errno values, so just pick the first. */ | |||
1016 | for (i = 0; i < nr; i++) { | |||
1017 | if (slots[i].error) { | |||
1018 | errno(*__error()) = slots[i].error; | |||
1019 | return -1; | |||
1020 | } | |||
1021 | } | |||
1022 | return 0; | |||
1023 | } | |||
1024 | ||||
1025 | ||||
1026 | int pipe_command(struct child_process *cmd, | |||
1027 | const char *in, size_t in_len, | |||
1028 | struct strbuf *out, size_t out_hint, | |||
1029 | struct strbuf *err, size_t err_hint) | |||
1030 | { | |||
1031 | struct io_pump io[3]; | |||
1032 | int nr = 0; | |||
1033 | ||||
1034 | if (in) | |||
1035 | cmd->in = -1; | |||
1036 | if (out) | |||
1037 | cmd->out = -1; | |||
1038 | if (err) | |||
1039 | cmd->err = -1; | |||
1040 | ||||
1041 | if (start_command(cmd) < 0) | |||
1042 | return -1; | |||
1043 | ||||
1044 | if (in) { | |||
1045 | io[nr].fd = cmd->in; | |||
1046 | io[nr].type = POLLOUT0x0004; | |||
1047 | io[nr].u.out.buf = in; | |||
1048 | io[nr].u.out.len = in_len; | |||
1049 | nr++; | |||
1050 | } | |||
1051 | if (out) { | |||
1052 | io[nr].fd = cmd->out; | |||
1053 | io[nr].type = POLLIN0x0001; | |||
1054 | io[nr].u.in.buf = out; | |||
1055 | io[nr].u.in.hint = out_hint; | |||
1056 | nr++; | |||
1057 | } | |||
1058 | if (err) { | |||
1059 | io[nr].fd = cmd->err; | |||
1060 | io[nr].type = POLLIN0x0001; | |||
1061 | io[nr].u.in.buf = err; | |||
1062 | io[nr].u.in.hint = err_hint; | |||
1063 | nr++; | |||
1064 | } | |||
1065 | ||||
1066 | if (pump_io(io, nr) < 0) { | |||
1067 | finish_command(cmd); /* throw away exit code */ | |||
1068 | return -1; | |||
1069 | } | |||
1070 | ||||
1071 | return finish_command(cmd); | |||
1072 | } | |||
1073 | ||||
1074 | enum child_state { | |||
1075 | GIT_CP_FREE, | |||
1076 | GIT_CP_WORKING, | |||
1077 | GIT_CP_WAIT_CLEANUP, | |||
1078 | }; | |||
1079 | ||||
1080 | struct parallel_processes { | |||
1081 | void *data; | |||
1082 | ||||
1083 | int max_processes; | |||
1084 | int nr_processes; | |||
1085 | ||||
1086 | get_next_task_fn get_next_task; | |||
1087 | start_failure_fn start_failure; | |||
1088 | task_finished_fn task_finished; | |||
1089 | ||||
1090 | struct { | |||
1091 | enum child_state state; | |||
1092 | struct child_process process; | |||
1093 | struct strbuf err; | |||
1094 | void *data; | |||
1095 | } *children; | |||
1096 | /* | |||
1097 | * The struct pollfd is logically part of *children, | |||
1098 | * but the system call expects it as its own array. | |||
1099 | */ | |||
1100 | struct pollfd *pfd; | |||
1101 | ||||
1102 | unsigned shutdown : 1; | |||
1103 | ||||
1104 | int output_owner; | |||
1105 | struct strbuf buffered_output; /* of finished children */ | |||
1106 | }; | |||
1107 | ||||
1108 | static int default_start_failure(struct strbuf *out, | |||
1109 | void *pp_cb, | |||
1110 | void *pp_task_cb) | |||
1111 | { | |||
1112 | return 0; | |||
1113 | } | |||
1114 | ||||
1115 | static int default_task_finished(int result, | |||
1116 | struct strbuf *out, | |||
1117 | void *pp_cb, | |||
1118 | void *pp_task_cb) | |||
1119 | { | |||
1120 | return 0; | |||
1121 | } | |||
1122 | ||||
1123 | static void kill_children(struct parallel_processes *pp, int signo) | |||
1124 | { | |||
1125 | int i, n = pp->max_processes; | |||
1126 | ||||
1127 | for (i = 0; i < n; i++) | |||
1128 | if (pp->children[i].state == GIT_CP_WORKING) | |||
1129 | kill(pp->children[i].process.pid, signo); | |||
1130 | } | |||
1131 | ||||
1132 | static struct parallel_processes *pp_for_signal; | |||
1133 | ||||
1134 | static void handle_children_on_signal(int signo) | |||
1135 | { | |||
1136 | kill_children(pp_for_signal, signo); | |||
1137 | sigchain_pop(signo); | |||
1138 | raise(signo); | |||
1139 | } | |||
1140 | ||||
1141 | static void pp_init(struct parallel_processes *pp, | |||
1142 | int n, | |||
1143 | get_next_task_fn get_next_task, | |||
1144 | start_failure_fn start_failure, | |||
1145 | task_finished_fn task_finished, | |||
1146 | void *data) | |||
1147 | { | |||
1148 | int i; | |||
1149 | ||||
1150 | if (n < 1) | |||
1151 | n = online_cpus(); | |||
1152 | ||||
1153 | pp->max_processes = n; | |||
1154 | ||||
1155 | trace_printf("run_processes_parallel: preparing to run up to %d tasks", n)trace_printf_key_fl("run-command.c", 1155, ((void*)0), "run_processes_parallel: preparing to run up to %d tasks" , n); | |||
1156 | ||||
1157 | pp->data = data; | |||
1158 | if (!get_next_task) | |||
1159 | die("BUG: you need to specify a get_next_task function"); | |||
1160 | pp->get_next_task = get_next_task; | |||
1161 | ||||
1162 | pp->start_failure = start_failure ? start_failure : default_start_failure; | |||
1163 | pp->task_finished = task_finished ? task_finished : default_task_finished; | |||
1164 | ||||
1165 | pp->nr_processes = 0; | |||
1166 | pp->output_owner = 0; | |||
1167 | pp->shutdown = 0; | |||
1168 | pp->children = xcalloc(n, sizeof(*pp->children)); | |||
1169 | pp->pfd = xcalloc(n, sizeof(*pp->pfd)); | |||
1170 | strbuf_init(&pp->buffered_output, 0); | |||
1171 | ||||
1172 | for (i = 0; i < n; i++) { | |||
1173 | strbuf_init(&pp->children[i].err, 0); | |||
1174 | child_process_init(&pp->children[i].process); | |||
1175 | pp->pfd[i].events = POLLIN0x0001 | POLLHUP0x0010; | |||
1176 | pp->pfd[i].fd = -1; | |||
1177 | } | |||
1178 | ||||
1179 | pp_for_signal = pp; | |||
1180 | sigchain_push_common(handle_children_on_signal); | |||
1181 | } | |||
1182 | ||||
1183 | static void pp_cleanup(struct parallel_processes *pp) | |||
1184 | { | |||
1185 | int i; | |||
1186 | ||||
1187 | trace_printf("run_processes_parallel: done")trace_printf_key_fl("run-command.c", 1187, ((void*)0), "run_processes_parallel: done" ); | |||
1188 | for (i = 0; i < pp->max_processes; i++) { | |||
1189 | strbuf_release(&pp->children[i].err); | |||
1190 | child_process_clear(&pp->children[i].process); | |||
1191 | } | |||
1192 | ||||
1193 | free(pp->children); | |||
1194 | free(pp->pfd); | |||
1195 | ||||
1196 | /* | |||
1197 | * When get_next_task added messages to the buffer in its last | |||
1198 | * iteration, the buffered output is non empty. | |||
1199 | */ | |||
1200 | strbuf_write(&pp->buffered_output, stderr__stderrp); | |||
1201 | strbuf_release(&pp->buffered_output); | |||
1202 | ||||
1203 | sigchain_pop_common(); | |||
1204 | } | |||
1205 | ||||
1206 | /* returns | |||
1207 | * 0 if a new task was started. | |||
1208 | * 1 if no new jobs was started (get_next_task ran out of work, non critical | |||
1209 | * problem with starting a new command) | |||
1210 | * <0 no new job was started, user wishes to shutdown early. Use negative code | |||
1211 | * to signal the children. | |||
1212 | */ | |||
1213 | static int pp_start_one(struct parallel_processes *pp) | |||
1214 | { | |||
1215 | int i, code; | |||
1216 | ||||
1217 | for (i = 0; i < pp->max_processes; i++) | |||
1218 | if (pp->children[i].state == GIT_CP_FREE) | |||
1219 | break; | |||
1220 | if (i == pp->max_processes) | |||
1221 | die("BUG: bookkeeping is hard"); | |||
1222 | ||||
1223 | code = pp->get_next_task(&pp->children[i].process, | |||
1224 | &pp->children[i].err, | |||
1225 | pp->data, | |||
1226 | &pp->children[i].data); | |||
1227 | if (!code) { | |||
1228 | strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); | |||
1229 | strbuf_reset(&pp->children[i].err)strbuf_setlen(&pp->children[i].err, 0); | |||
1230 | return 1; | |||
1231 | } | |||
1232 | pp->children[i].process.err = -1; | |||
1233 | pp->children[i].process.stdout_to_stderr = 1; | |||
1234 | pp->children[i].process.no_stdin = 1; | |||
1235 | ||||
1236 | if (start_command(&pp->children[i].process)) { | |||
1237 | code = pp->start_failure(&pp->children[i].err, | |||
1238 | pp->data, | |||
1239 | &pp->children[i].data); | |||
1240 | strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); | |||
1241 | strbuf_reset(&pp->children[i].err)strbuf_setlen(&pp->children[i].err, 0); | |||
1242 | if (code) | |||
1243 | pp->shutdown = 1; | |||
1244 | return code; | |||
1245 | } | |||
1246 | ||||
1247 | pp->nr_processes++; | |||
1248 | pp->children[i].state = GIT_CP_WORKING; | |||
1249 | pp->pfd[i].fd = pp->children[i].process.err; | |||
1250 | return 0; | |||
1251 | } | |||
1252 | ||||
1253 | static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout) | |||
1254 | { | |||
1255 | int i; | |||
1256 | ||||
1257 | while ((i = poll(pp->pfd, pp->max_processes, output_timeout)) < 0) { | |||
1258 | if (errno(*__error()) == EINTR4) | |||
1259 | continue; | |||
1260 | pp_cleanup(pp); | |||
1261 | die_errno("poll"); | |||
1262 | } | |||
1263 | ||||
1264 | /* Buffer output from all pipes. */ | |||
1265 | for (i = 0; i < pp->max_processes; i++) { | |||
1266 | if (pp->children[i].state == GIT_CP_WORKING && | |||
1267 | pp->pfd[i].revents & (POLLIN0x0001 | POLLHUP0x0010)) { | |||
1268 | int n = strbuf_read_once(&pp->children[i].err, | |||
1269 | pp->children[i].process.err, 0); | |||
1270 | if (n == 0) { | |||
1271 | close(pp->children[i].process.err); | |||
1272 | pp->children[i].state = GIT_CP_WAIT_CLEANUP; | |||
1273 | } else if (n < 0) | |||
1274 | if (errno(*__error()) != EAGAIN35) | |||
1275 | die_errno("read"); | |||
1276 | } | |||
1277 | } | |||
1278 | } | |||
1279 | ||||
1280 | static void pp_output(struct parallel_processes *pp) | |||
1281 | { | |||
1282 | int i = pp->output_owner; | |||
1283 | if (pp->children[i].state == GIT_CP_WORKING && | |||
1284 | pp->children[i].err.len) { | |||
1285 | strbuf_write(&pp->children[i].err, stderr__stderrp); | |||
1286 | strbuf_reset(&pp->children[i].err)strbuf_setlen(&pp->children[i].err, 0); | |||
1287 | } | |||
1288 | } | |||
1289 | ||||
1290 | static int pp_collect_finished(struct parallel_processes *pp) | |||
1291 | { | |||
1292 | int i, code; | |||
1293 | int n = pp->max_processes; | |||
1294 | int result = 0; | |||
1295 | ||||
1296 | while (pp->nr_processes > 0) { | |||
1297 | for (i = 0; i < pp->max_processes; i++) | |||
1298 | if (pp->children[i].state == GIT_CP_WAIT_CLEANUP) | |||
1299 | break; | |||
1300 | if (i == pp->max_processes) | |||
1301 | break; | |||
1302 | ||||
1303 | code = finish_command(&pp->children[i].process); | |||
1304 | ||||
1305 | code = pp->task_finished(code, | |||
1306 | &pp->children[i].err, pp->data, | |||
1307 | &pp->children[i].data); | |||
1308 | ||||
1309 | if (code) | |||
1310 | result = code; | |||
1311 | if (code < 0) | |||
1312 | break; | |||
1313 | ||||
1314 | pp->nr_processes--; | |||
1315 | pp->children[i].state = GIT_CP_FREE; | |||
1316 | pp->pfd[i].fd = -1; | |||
1317 | child_process_init(&pp->children[i].process); | |||
1318 | ||||
1319 | if (i != pp->output_owner) { | |||
1320 | strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); | |||
1321 | strbuf_reset(&pp->children[i].err)strbuf_setlen(&pp->children[i].err, 0); | |||
1322 | } else { | |||
1323 | strbuf_write(&pp->children[i].err, stderr__stderrp); | |||
1324 | strbuf_reset(&pp->children[i].err)strbuf_setlen(&pp->children[i].err, 0); | |||
1325 | ||||
1326 | /* Output all other finished child processes */ | |||
1327 | strbuf_write(&pp->buffered_output, stderr__stderrp); | |||
1328 | strbuf_reset(&pp->buffered_output)strbuf_setlen(&pp->buffered_output, 0); | |||
1329 | ||||
1330 | /* | |||
1331 | * Pick next process to output live. | |||
1332 | * NEEDSWORK: | |||
1333 | * For now we pick it randomly by doing a round | |||
1334 | * robin. Later we may want to pick the one with | |||
1335 | * the most output or the longest or shortest | |||
1336 | * running process time. | |||
1337 | */ | |||
1338 | for (i = 0; i < n; i++) | |||
1339 | if (pp->children[(pp->output_owner + i) % n].state == GIT_CP_WORKING) | |||
1340 | break; | |||
1341 | pp->output_owner = (pp->output_owner + i) % n; | |||
1342 | } | |||
1343 | } | |||
1344 | return result; | |||
1345 | } | |||
1346 | ||||
1347 | int run_processes_parallel(int n, | |||
1348 | get_next_task_fn get_next_task, | |||
1349 | start_failure_fn start_failure, | |||
1350 | task_finished_fn task_finished, | |||
1351 | void *pp_cb) | |||
1352 | { | |||
1353 | int i, code; | |||
1354 | int output_timeout = 100; | |||
1355 | int spawn_cap = 4; | |||
1356 | struct parallel_processes pp; | |||
1357 | ||||
1358 | pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb); | |||
1359 | while (1) { | |||
1360 | for (i = 0; | |||
1361 | i < spawn_cap && !pp.shutdown && | |||
1362 | pp.nr_processes < pp.max_processes; | |||
1363 | i++) { | |||
1364 | code = pp_start_one(&pp); | |||
1365 | if (!code) | |||
1366 | continue; | |||
1367 | if (code < 0) { | |||
1368 | pp.shutdown = 1; | |||
1369 | kill_children(&pp, -code); | |||
1370 | } | |||
1371 | break; | |||
1372 | } | |||
1373 | if (!pp.nr_processes) | |||
1374 | break; | |||
1375 | pp_buffer_stderr(&pp, output_timeout); | |||
1376 | pp_output(&pp); | |||
1377 | code = pp_collect_finished(&pp); | |||
1378 | if (code) { | |||
1379 | pp.shutdown = 1; | |||
1380 | if (code < 0) | |||
1381 | kill_children(&pp, -code); | |||
1382 | } | |||
1383 | } | |||
1384 | ||||
1385 | pp_cleanup(&pp); | |||
1386 | return 0; | |||
1387 | } |