| 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 | } |