summaryrefslogtreecommitdiff
path: root/run-command.c
diff options
context:
space:
mode:
Diffstat (limited to 'run-command.c')
-rw-r--r--run-command.c97
1 files changed, 41 insertions, 56 deletions
diff --git a/run-command.c b/run-command.c
index f40df01..69dde42 100644
--- a/run-command.c
+++ b/run-command.c
@@ -340,15 +340,6 @@ static void child_close_pair(int fd[2])
child_close(fd[1]);
}
-/*
- * parent will make it look like the child spewed a fatal error and died
- * this is needed to prevent changes to t0061.
- */
-static void fake_fatal(const char *err, va_list params)
-{
- vreportf("fatal: ", err, params);
-}
-
static void child_error_fn(const char *err, va_list params)
{
const char msg[] = "error() should not be called in child\n";
@@ -372,15 +363,16 @@ static void NORETURN child_die_fn(const char *err, va_list params)
static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
{
static void (*old_errfn)(const char *err, va_list params);
+ report_fn die_message_routine = get_die_message_routine();
old_errfn = get_error_routine();
- set_error_routine(fake_fatal);
+ set_error_routine(die_message_routine);
errno = cerr->syserr;
switch (cerr->err) {
case CHILD_ERR_CHDIR:
error_errno("exec '%s': cd to '%s' failed",
- cmd->argv[0], cmd->dir);
+ cmd->args.v[0], cmd->dir);
break;
case CHILD_ERR_DUP2:
error_errno("dup2() in child failed");
@@ -392,12 +384,12 @@ static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
error_errno("sigprocmask failed restoring signals");
break;
case CHILD_ERR_ENOENT:
- error_errno("cannot run %s", cmd->argv[0]);
+ error_errno("cannot run %s", cmd->args.v[0]);
break;
case CHILD_ERR_SILENT:
break;
case CHILD_ERR_ERRNO:
- error_errno("cannot exec '%s'", cmd->argv[0]);
+ error_errno("cannot exec '%s'", cmd->args.v[0]);
break;
}
set_error_routine(old_errfn);
@@ -405,7 +397,7 @@ static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
static int prepare_cmd(struct strvec *out, const struct child_process *cmd)
{
- if (!cmd->argv[0])
+ if (!cmd->args.v[0])
BUG("command is empty");
/*
@@ -415,11 +407,11 @@ static int prepare_cmd(struct strvec *out, const struct child_process *cmd)
strvec_push(out, SHELL_PATH);
if (cmd->git_cmd) {
- prepare_git_cmd(out, cmd->argv);
+ prepare_git_cmd(out, cmd->args.v);
} else if (cmd->use_shell) {
- prepare_shell_cmd(out, cmd->argv);
+ prepare_shell_cmd(out, cmd->args.v);
} else {
- strvec_pushv(out, cmd->argv);
+ strvec_pushv(out, cmd->args.v);
}
/*
@@ -552,20 +544,17 @@ static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
; /* nothing */
- if (in_signal) {
- if (WIFEXITED(status))
- code = WEXITSTATUS(status);
- return code;
- }
if (waiting < 0) {
failed_errno = errno;
- error_errno("waitpid for %s failed", argv0);
+ if (!in_signal)
+ error_errno("waitpid for %s failed", argv0);
} else if (waiting != pid) {
- error("waitpid is confused (%s)", argv0);
+ if (!in_signal)
+ error("waitpid is confused (%s)", argv0);
} else if (WIFSIGNALED(status)) {
code = WTERMSIG(status);
- if (code != SIGINT && code != SIGQUIT && code != SIGPIPE)
+ if (!in_signal && code != SIGINT && code != SIGQUIT && code != SIGPIPE)
error("%s died of signal %d", argv0, code);
/*
* This return value is chosen so that code & 0xff
@@ -576,10 +565,12 @@ static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
} else if (WIFEXITED(status)) {
code = WEXITSTATUS(status);
} else {
- error("waitpid is confused (%s)", argv0);
+ if (!in_signal)
+ error("waitpid is confused (%s)", argv0);
}
- clear_child_for_cleanup(pid);
+ if (!in_signal)
+ clear_child_for_cleanup(pid);
errno = failed_errno;
return code;
@@ -655,15 +646,10 @@ static void trace_run_command(const struct child_process *cp)
sq_quote_buf_pretty(&buf, cp->dir);
strbuf_addch(&buf, ';');
}
- /*
- * The caller is responsible for initializing cp->env from
- * cp->env_array if needed. We only check one place.
- */
- if (cp->env)
- trace_add_env(&buf, cp->env);
+ trace_add_env(&buf, cp->env_array.v);
if (cp->git_cmd)
strbuf_addstr(&buf, " git");
- sq_quote_argv_pretty(&buf, cp->argv);
+ sq_quote_argv_pretty(&buf, cp->args.v);
trace_printf("%s", buf.buf);
strbuf_release(&buf);
@@ -676,11 +662,6 @@ int start_command(struct child_process *cmd)
int failed_errno;
char *str;
- if (!cmd->argv)
- cmd->argv = cmd->args.v;
- if (!cmd->env)
- cmd->env = cmd->env_array.v;
-
/*
* In case of errors we must keep the promise to close FDs
* that have been passed in via ->in and ->out.
@@ -729,7 +710,7 @@ int start_command(struct child_process *cmd)
str = "standard error";
fail_pipe:
error("cannot create %s pipe for %s: %s",
- str, cmd->argv[0], strerror(failed_errno));
+ str, cmd->args.v[0], strerror(failed_errno));
child_process_clear(cmd);
errno = failed_errno;
return -1;
@@ -758,7 +739,7 @@ fail_pipe:
failed_errno = errno;
cmd->pid = -1;
if (!cmd->silent_exec_failure)
- error_errno("cannot run %s", cmd->argv[0]);
+ error_errno("cannot run %s", cmd->args.v[0]);
goto end_of_spawn;
}
@@ -770,7 +751,7 @@ fail_pipe:
set_cloexec(null_fd);
}
- childenv = prep_childenv(cmd->env);
+ childenv = prep_childenv(cmd->env_array.v);
atfork_prepare(&as);
/*
@@ -868,7 +849,7 @@ fail_pipe:
}
atfork_parent(&as);
if (cmd->pid < 0)
- error_errno("cannot fork() for %s", cmd->argv[0]);
+ error_errno("cannot fork() for %s", cmd->args.v[0]);
else if (cmd->clean_on_exit)
mark_child_for_cleanup(cmd->pid, cmd);
@@ -885,7 +866,7 @@ fail_pipe:
* At this point we know that fork() succeeded, but exec()
* failed. Errors have been reported to our stderr.
*/
- wait_or_whine(cmd->pid, cmd->argv[0], 0);
+ wait_or_whine(cmd->pid, cmd->args.v[0], 0);
child_err_spew(cmd, &cerr);
failed_errno = errno;
cmd->pid = -1;
@@ -902,7 +883,7 @@ end_of_spawn:
#else
{
int fhin = 0, fhout = 1, fherr = 2;
- const char **sargv = cmd->argv;
+ const char **sargv = cmd->args.v;
struct strvec nargv = STRVEC_INIT;
if (cmd->no_stdin)
@@ -929,20 +910,20 @@ end_of_spawn:
fhout = dup(cmd->out);
if (cmd->git_cmd)
- cmd->argv = prepare_git_cmd(&nargv, cmd->argv);
+ cmd->args.v = prepare_git_cmd(&nargv, sargv);
else if (cmd->use_shell)
- cmd->argv = prepare_shell_cmd(&nargv, cmd->argv);
+ cmd->args.v = prepare_shell_cmd(&nargv, sargv);
- cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env,
+ cmd->pid = mingw_spawnvpe(cmd->args.v[0], cmd->args.v, (char**) cmd->env_array.v,
cmd->dir, fhin, fhout, fherr);
failed_errno = errno;
if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
- error_errno("cannot spawn %s", cmd->argv[0]);
+ error_errno("cannot spawn %s", cmd->args.v[0]);
if (cmd->clean_on_exit && cmd->pid >= 0)
mark_child_for_cleanup(cmd->pid, cmd);
strvec_clear(&nargv);
- cmd->argv = sargv;
+ cmd->args.v = sargv;
if (fhin != 0)
close(fhin);
if (fhout != 1)
@@ -992,7 +973,7 @@ end_of_spawn:
int finish_command(struct child_process *cmd)
{
- int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
+ int ret = wait_or_whine(cmd->pid, cmd->args.v[0], 0);
trace2_child_exit(cmd, ret);
child_process_clear(cmd);
invalidate_lstat_cache();
@@ -1001,7 +982,7 @@ int finish_command(struct child_process *cmd)
int finish_command_in_signal(struct child_process *cmd)
{
- int ret = wait_or_whine(cmd->pid, cmd->argv[0], 1);
+ int ret = wait_or_whine(cmd->pid, cmd->args.v[0], 1);
trace2_child_exit(cmd, ret);
return ret;
}
@@ -1039,7 +1020,7 @@ int run_command_v_opt_cd_env_tr2(const char **argv, int opt, const char *dir,
const char *const *env, const char *tr2_class)
{
struct child_process cmd = CHILD_PROCESS_INIT;
- cmd.argv = argv;
+ strvec_pushv(&cmd.args, argv);
cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
@@ -1049,7 +1030,8 @@ int run_command_v_opt_cd_env_tr2(const char **argv, int opt, const char *dir,
cmd.wait_after_clean = opt & RUN_WAIT_AFTER_CLEAN ? 1 : 0;
cmd.close_object_store = opt & RUN_CLOSE_OBJECT_STORE ? 1 : 0;
cmd.dir = dir;
- cmd.env = env;
+ if (env)
+ strvec_pushv(&cmd.env_array, (const char **)env);
cmd.trace2_child_class = tr2_class;
return run_command(&cmd);
}
@@ -1082,7 +1064,9 @@ static void *run_thread(void *data)
static NORETURN void die_async(const char *err, va_list params)
{
- vreportf("fatal: ", err, params);
+ report_fn die_message_fn = get_die_message_routine();
+
+ die_message_fn(err, params);
if (in_async()) {
struct async *async = pthread_getspecific(async_key);
@@ -1335,7 +1319,8 @@ int run_hook_ve(const char *const *env, const char *name, va_list args)
strvec_push(&hook.args, p);
while ((p = va_arg(args, const char *)))
strvec_push(&hook.args, p);
- hook.env = env;
+ if (env)
+ strvec_pushv(&hook.env_array, (const char **)env);
hook.no_stdin = 1;
hook.stdout_to_stderr = 1;
hook.trace2_hook_name = name;