run-command: store an optional argv_array
All child_process structs need to point to an argv. For flexibility, we do not mandate the use of a dynamic argv_array. However, because the child_process does not own the memory, this can make memory management with a separate argv_array difficult. For example, if a function calls start_command but not finish_command, the argv memory must persist. The code needs to arrange to clean up the argv_array separately after finish_command runs. As a result, some of our code in this situation just leaks the memory. To help such cases, this patch adds a built-in argv_array to the child_process, which gets cleaned up automatically (both in finish_command and when start_command fails). Callers may use it if they choose, but can continue to use the raw argv if they wish. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
6308767f0b
commit
c460c0ecdc
|
@ -109,6 +109,13 @@ terminated), of which .argv[0] is the program name to run (usually
|
||||||
without a path). If the command to run is a git command, set argv[0] to
|
without a path). If the command to run is a git command, set argv[0] to
|
||||||
the command name without the 'git-' prefix and set .git_cmd = 1.
|
the command name without the 'git-' prefix and set .git_cmd = 1.
|
||||||
|
|
||||||
|
Note that the ownership of the memory pointed to by .argv stays with the
|
||||||
|
caller, but it should survive until `finish_command` completes. If the
|
||||||
|
.argv member is NULL, `start_command` will point it at the .args
|
||||||
|
`argv_array` (so you may use one or the other, but you must use exactly
|
||||||
|
one). The memory in .args will be cleaned up automatically during
|
||||||
|
`finish_command` (or during `start_command` when it is unsuccessful).
|
||||||
|
|
||||||
The members .in, .out, .err are used to redirect stdin, stdout,
|
The members .in, .out, .err are used to redirect stdin, stdout,
|
||||||
stderr as follows:
|
stderr as follows:
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,9 @@ int start_command(struct child_process *cmd)
|
||||||
int failed_errno;
|
int failed_errno;
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
|
if (!cmd->argv)
|
||||||
|
cmd->argv = cmd->args.argv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In case of errors we must keep the promise to close FDs
|
* In case of errors we must keep the promise to close FDs
|
||||||
* that have been passed in via ->in and ->out.
|
* that have been passed in via ->in and ->out.
|
||||||
|
@ -328,6 +331,7 @@ int start_command(struct child_process *cmd)
|
||||||
fail_pipe:
|
fail_pipe:
|
||||||
error("cannot create %s pipe for %s: %s",
|
error("cannot create %s pipe for %s: %s",
|
||||||
str, cmd->argv[0], strerror(failed_errno));
|
str, cmd->argv[0], strerror(failed_errno));
|
||||||
|
argv_array_clear(&cmd->args);
|
||||||
errno = failed_errno;
|
errno = failed_errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -519,6 +523,7 @@ fail_pipe:
|
||||||
close_pair(fderr);
|
close_pair(fderr);
|
||||||
else if (cmd->err)
|
else if (cmd->err)
|
||||||
close(cmd->err);
|
close(cmd->err);
|
||||||
|
argv_array_clear(&cmd->args);
|
||||||
errno = failed_errno;
|
errno = failed_errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -543,7 +548,9 @@ fail_pipe:
|
||||||
|
|
||||||
int finish_command(struct child_process *cmd)
|
int finish_command(struct child_process *cmd)
|
||||||
{
|
{
|
||||||
return wait_or_whine(cmd->pid, cmd->argv[0]);
|
int ret = wait_or_whine(cmd->pid, cmd->argv[0]);
|
||||||
|
argv_array_clear(&cmd->args);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_command(struct child_process *cmd)
|
int run_command(struct child_process *cmd)
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "argv-array.h"
|
||||||
|
|
||||||
struct child_process {
|
struct child_process {
|
||||||
const char **argv;
|
const char **argv;
|
||||||
|
struct argv_array args;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
/*
|
/*
|
||||||
* Using .in, .out, .err:
|
* Using .in, .out, .err:
|
||||||
|
|
Loading…
Reference in New Issue