2005-07-31 21:17:43 +02:00
|
|
|
#include "cache.h"
|
|
|
|
#include "run-command.h"
|
2006-01-11 03:12:17 +01:00
|
|
|
#include "exec_cmd.h"
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
#include "sigchain.h"
|
2011-09-13 23:58:25 +02:00
|
|
|
#include "argv-array.h"
|
2005-07-31 21:17:43 +02:00
|
|
|
|
2012-03-31 03:33:21 +02:00
|
|
|
#ifndef SHELL_PATH
|
|
|
|
# define SHELL_PATH "/bin/sh"
|
|
|
|
#endif
|
|
|
|
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
struct child_to_clean {
|
|
|
|
pid_t pid;
|
|
|
|
struct child_to_clean *next;
|
|
|
|
};
|
|
|
|
static struct child_to_clean *children_to_clean;
|
|
|
|
static int installed_child_cleanup_handler;
|
|
|
|
|
|
|
|
static void cleanup_children(int sig)
|
|
|
|
{
|
|
|
|
while (children_to_clean) {
|
|
|
|
struct child_to_clean *p = children_to_clean;
|
|
|
|
children_to_clean = p->next;
|
|
|
|
kill(p->pid, sig);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cleanup_children_on_signal(int sig)
|
|
|
|
{
|
|
|
|
cleanup_children(sig);
|
|
|
|
sigchain_pop(sig);
|
|
|
|
raise(sig);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cleanup_children_on_exit(void)
|
|
|
|
{
|
|
|
|
cleanup_children(SIGTERM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mark_child_for_cleanup(pid_t pid)
|
|
|
|
{
|
|
|
|
struct child_to_clean *p = xmalloc(sizeof(*p));
|
|
|
|
p->pid = pid;
|
|
|
|
p->next = children_to_clean;
|
|
|
|
children_to_clean = p;
|
|
|
|
|
|
|
|
if (!installed_child_cleanup_handler) {
|
|
|
|
atexit(cleanup_children_on_exit);
|
|
|
|
sigchain_push_common(cleanup_children_on_signal);
|
|
|
|
installed_child_cleanup_handler = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void clear_child_for_cleanup(pid_t pid)
|
|
|
|
{
|
2012-09-11 16:32:47 +02:00
|
|
|
struct child_to_clean **pp;
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
|
2012-09-11 16:32:47 +02:00
|
|
|
for (pp = &children_to_clean; *pp; pp = &(*pp)->next) {
|
|
|
|
struct child_to_clean *clean_me = *pp;
|
|
|
|
|
|
|
|
if (clean_me->pid == pid) {
|
|
|
|
*pp = clean_me->next;
|
|
|
|
free(clean_me);
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-12 19:37:28 +01:00
|
|
|
static inline void close_pair(int fd[2])
|
|
|
|
{
|
|
|
|
close(fd[0]);
|
|
|
|
close(fd[1]);
|
|
|
|
}
|
|
|
|
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
#ifndef WIN32
|
2007-03-12 19:37:55 +01:00
|
|
|
static inline void dup_devnull(int to)
|
|
|
|
{
|
|
|
|
int fd = open("/dev/null", O_RDWR);
|
|
|
|
dup2(fd, to);
|
|
|
|
close(fd);
|
|
|
|
}
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
#endif
|
2007-03-12 19:37:55 +01:00
|
|
|
|
2012-03-30 09:52:18 +02:00
|
|
|
static char *locate_in_PATH(const char *file)
|
|
|
|
{
|
|
|
|
const char *p = getenv("PATH");
|
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (!p || !*p)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
const char *end = strchrnul(p, ':');
|
|
|
|
|
|
|
|
strbuf_reset(&buf);
|
|
|
|
|
|
|
|
/* POSIX specifies an empty entry as the current directory. */
|
|
|
|
if (end != p) {
|
|
|
|
strbuf_add(&buf, p, end - p);
|
|
|
|
strbuf_addch(&buf, '/');
|
|
|
|
}
|
|
|
|
strbuf_addstr(&buf, file);
|
|
|
|
|
|
|
|
if (!access(buf.buf, F_OK))
|
|
|
|
return strbuf_detach(&buf, NULL);
|
|
|
|
|
|
|
|
if (!*end)
|
|
|
|
break;
|
|
|
|
p = end + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
strbuf_release(&buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int exists_in_PATH(const char *file)
|
|
|
|
{
|
|
|
|
char *r = locate_in_PATH(file);
|
|
|
|
free(r);
|
|
|
|
return r != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sane_execvp(const char *file, char * const argv[])
|
|
|
|
{
|
|
|
|
if (!execvp(file, argv))
|
|
|
|
return 0; /* cannot happen ;-) */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When a command can't be found because one of the directories
|
|
|
|
* listed in $PATH is unsearchable, execvp reports EACCES, but
|
|
|
|
* careful usability testing (read: analysis of occasional bug
|
|
|
|
* reports) reveals that "No such file or directory" is more
|
|
|
|
* intuitive.
|
|
|
|
*
|
|
|
|
* We avoid commands with "/", because execvp will not do $PATH
|
|
|
|
* lookups in that case.
|
|
|
|
*
|
|
|
|
* The reassignment of EACCES to errno looks like a no-op below,
|
|
|
|
* but we need to protect against exists_in_PATH overwriting errno.
|
|
|
|
*/
|
|
|
|
if (errno == EACCES && !strchr(file, '/'))
|
|
|
|
errno = exists_in_PATH(file) ? EACCES : ENOENT;
|
2012-07-31 21:51:30 +02:00
|
|
|
else if (errno == ENOTDIR && !strchr(file, '/'))
|
|
|
|
errno = ENOENT;
|
2012-03-30 09:52:18 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-12-30 11:53:16 +01:00
|
|
|
static const char **prepare_shell_cmd(const char **argv)
|
|
|
|
{
|
|
|
|
int argc, nargc = 0;
|
|
|
|
const char **nargv;
|
|
|
|
|
|
|
|
for (argc = 0; argv[argc]; argc++)
|
|
|
|
; /* just counting */
|
|
|
|
/* +1 for NULL, +3 for "sh -c" plus extra $0 */
|
|
|
|
nargv = xmalloc(sizeof(*nargv) * (argc + 1 + 3));
|
|
|
|
|
|
|
|
if (argc < 1)
|
|
|
|
die("BUG: shell command is empty");
|
|
|
|
|
2009-12-30 11:55:36 +01:00
|
|
|
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
|
Do not use SHELL_PATH from build system in prepare_shell_cmd on Windows
The recent change to use SHELL_PATH instead of "sh" to spawn shell commands
is not suited for Windows:
- The default setting, "/bin/sh", does not work when git has to run the
shell because it is a POSIX style path, but not a proper Windows style
path.
- If it worked, it would hard-code a position in the files system where
the shell is expected, making git (more precisely, the POSIX toolset that
is needed alongside git) non-relocatable. But we cannot sacrifice
relocatability on Windows.
- Apart from that, even though the Makefile leaves SHELL_PATH set to
"/bin/sh" for the Windows builds, the build system passes a mangled path
to the compiler, and something like "D:/Src/msysgit/bin/sh" is used,
which is doubly bad because it points to where /bin/sh resolves to on
the system where git was built.
- Finally, the system's CreateProcess() function that is used under
mingw.c's hood does not work with forward slashes and cannot find the
shell.
Undo the earlier change on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 09:03:21 +02:00
|
|
|
#ifndef WIN32
|
2012-03-31 03:33:21 +02:00
|
|
|
nargv[nargc++] = SHELL_PATH;
|
Do not use SHELL_PATH from build system in prepare_shell_cmd on Windows
The recent change to use SHELL_PATH instead of "sh" to spawn shell commands
is not suited for Windows:
- The default setting, "/bin/sh", does not work when git has to run the
shell because it is a POSIX style path, but not a proper Windows style
path.
- If it worked, it would hard-code a position in the files system where
the shell is expected, making git (more precisely, the POSIX toolset that
is needed alongside git) non-relocatable. But we cannot sacrifice
relocatability on Windows.
- Apart from that, even though the Makefile leaves SHELL_PATH set to
"/bin/sh" for the Windows builds, the build system passes a mangled path
to the compiler, and something like "D:/Src/msysgit/bin/sh" is used,
which is doubly bad because it points to where /bin/sh resolves to on
the system where git was built.
- Finally, the system's CreateProcess() function that is used under
mingw.c's hood does not work with forward slashes and cannot find the
shell.
Undo the earlier change on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 09:03:21 +02:00
|
|
|
#else
|
|
|
|
nargv[nargc++] = "sh";
|
|
|
|
#endif
|
2009-12-30 11:55:36 +01:00
|
|
|
nargv[nargc++] = "-c";
|
2009-12-30 11:53:16 +01:00
|
|
|
|
2009-12-30 11:55:36 +01:00
|
|
|
if (argc < 2)
|
|
|
|
nargv[nargc++] = argv[0];
|
|
|
|
else {
|
|
|
|
struct strbuf arg0 = STRBUF_INIT;
|
|
|
|
strbuf_addf(&arg0, "%s \"$@\"", argv[0]);
|
|
|
|
nargv[nargc++] = strbuf_detach(&arg0, NULL);
|
|
|
|
}
|
2009-12-30 11:53:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (argc = 0; argv[argc]; argc++)
|
|
|
|
nargv[nargc++] = argv[argc];
|
|
|
|
nargv[nargc] = NULL;
|
|
|
|
|
|
|
|
return nargv;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
static int execv_shell_cmd(const char **argv)
|
|
|
|
{
|
|
|
|
const char **nargv = prepare_shell_cmd(argv);
|
|
|
|
trace_argv_printf(nargv, "trace: exec:");
|
2012-03-30 09:52:18 +02:00
|
|
|
sane_execvp(nargv[0], (char **)nargv);
|
2009-12-30 11:53:16 +01:00
|
|
|
free(nargv);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-01-10 14:07:52 +01:00
|
|
|
#ifndef WIN32
|
|
|
|
static int child_err = 2;
|
2010-01-10 14:11:22 +01:00
|
|
|
static int child_notifier = -1;
|
|
|
|
|
|
|
|
static void notify_parent(void)
|
|
|
|
{
|
2011-04-20 12:40:05 +02:00
|
|
|
/*
|
|
|
|
* execvp failed. If possible, we'd like to let start_command
|
|
|
|
* know, so failures like ENOENT can be handled right away; but
|
|
|
|
* otherwise, finish_command will still report the error.
|
|
|
|
*/
|
|
|
|
xwrite(child_notifier, "", 1);
|
2010-01-10 14:11:22 +01:00
|
|
|
}
|
2010-01-10 14:07:52 +01:00
|
|
|
|
|
|
|
static NORETURN void die_child(const char *err, va_list params)
|
|
|
|
{
|
2011-07-27 23:32:34 +02:00
|
|
|
vwritef(child_err, "fatal: ", err, params);
|
2010-01-10 14:07:52 +01:00
|
|
|
exit(128);
|
|
|
|
}
|
2011-07-27 23:32:34 +02:00
|
|
|
|
|
|
|
static void error_child(const char *err, va_list params)
|
|
|
|
{
|
|
|
|
vwritef(child_err, "error: ", err, params);
|
|
|
|
}
|
2010-03-06 16:40:42 +01:00
|
|
|
#endif
|
2010-01-10 14:07:52 +01:00
|
|
|
|
|
|
|
static inline void set_cloexec(int fd)
|
|
|
|
{
|
|
|
|
int flags = fcntl(fd, F_GETFD);
|
|
|
|
if (flags >= 0)
|
|
|
|
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
|
|
|
|
}
|
|
|
|
|
2012-11-30 23:40:50 +01:00
|
|
|
static int wait_or_whine(pid_t pid, const char *argv0)
|
2010-01-10 14:08:45 +01:00
|
|
|
{
|
|
|
|
int status, code = -1;
|
|
|
|
pid_t waiting;
|
|
|
|
int failed_errno = 0;
|
|
|
|
|
|
|
|
while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
|
|
|
|
; /* nothing */
|
|
|
|
|
|
|
|
if (waiting < 0) {
|
|
|
|
failed_errno = errno;
|
|
|
|
error("waitpid for %s failed: %s", argv0, strerror(errno));
|
|
|
|
} else if (waiting != pid) {
|
|
|
|
error("waitpid is confused (%s)", argv0);
|
|
|
|
} else if (WIFSIGNALED(status)) {
|
|
|
|
code = WTERMSIG(status);
|
2012-11-30 23:41:38 +01:00
|
|
|
if (code != SIGINT && code != SIGQUIT)
|
|
|
|
error("%s died of signal %d", argv0, code);
|
2010-01-10 14:08:45 +01:00
|
|
|
/*
|
|
|
|
* This return value is chosen so that code & 0xff
|
|
|
|
* mimics the exit code that a POSIX shell would report for
|
|
|
|
* a program that died from this signal.
|
|
|
|
*/
|
|
|
|
code -= 128;
|
|
|
|
} else if (WIFEXITED(status)) {
|
|
|
|
code = WEXITSTATUS(status);
|
|
|
|
/*
|
|
|
|
* Convert special exit code when execvp failed.
|
|
|
|
*/
|
|
|
|
if (code == 127) {
|
|
|
|
code = -1;
|
|
|
|
failed_errno = ENOENT;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error("waitpid is confused (%s)", argv0);
|
|
|
|
}
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
|
|
|
|
clear_child_for_cleanup(pid);
|
|
|
|
|
2010-01-10 14:08:45 +01:00
|
|
|
errno = failed_errno;
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
2007-03-10 09:28:05 +01:00
|
|
|
int start_command(struct child_process *cmd)
|
2005-07-31 21:17:43 +02:00
|
|
|
{
|
2007-10-19 21:47:58 +02:00
|
|
|
int need_in, need_out, need_err;
|
|
|
|
int fdin[2], fdout[2], fderr[2];
|
2009-08-04 11:28:40 +02:00
|
|
|
int failed_errno = failed_errno;
|
2007-03-10 09:28:08 +01:00
|
|
|
|
2008-02-21 23:42:56 +01:00
|
|
|
/*
|
|
|
|
* In case of errors we must keep the promise to close FDs
|
|
|
|
* that have been passed in via ->in and ->out.
|
|
|
|
*/
|
|
|
|
|
2007-03-12 19:37:55 +01:00
|
|
|
need_in = !cmd->no_stdin && cmd->in < 0;
|
2007-03-10 09:28:08 +01:00
|
|
|
if (need_in) {
|
2008-02-21 23:42:56 +01:00
|
|
|
if (pipe(fdin) < 0) {
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
failed_errno = errno;
|
2008-02-21 23:42:56 +01:00
|
|
|
if (cmd->out > 0)
|
|
|
|
close(cmd->out);
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
goto fail_pipe;
|
2008-02-21 23:42:56 +01:00
|
|
|
}
|
2007-03-10 09:28:08 +01:00
|
|
|
cmd->in = fdin[1];
|
|
|
|
}
|
|
|
|
|
2007-03-12 19:37:55 +01:00
|
|
|
need_out = !cmd->no_stdout
|
|
|
|
&& !cmd->stdout_to_stderr
|
|
|
|
&& cmd->out < 0;
|
2007-03-12 19:37:45 +01:00
|
|
|
if (need_out) {
|
|
|
|
if (pipe(fdout) < 0) {
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
failed_errno = errno;
|
2007-03-12 19:37:45 +01:00
|
|
|
if (need_in)
|
|
|
|
close_pair(fdin);
|
2008-02-21 23:42:56 +01:00
|
|
|
else if (cmd->in)
|
|
|
|
close(cmd->in);
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
goto fail_pipe;
|
2007-03-12 19:37:45 +01:00
|
|
|
}
|
|
|
|
cmd->out = fdout[0];
|
|
|
|
}
|
|
|
|
|
2007-11-11 08:29:37 +01:00
|
|
|
need_err = !cmd->no_stderr && cmd->err < 0;
|
2007-10-19 21:47:58 +02:00
|
|
|
if (need_err) {
|
|
|
|
if (pipe(fderr) < 0) {
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
failed_errno = errno;
|
2007-10-19 21:47:58 +02:00
|
|
|
if (need_in)
|
|
|
|
close_pair(fdin);
|
2008-02-21 23:42:56 +01:00
|
|
|
else if (cmd->in)
|
|
|
|
close(cmd->in);
|
2007-10-19 21:47:58 +02:00
|
|
|
if (need_out)
|
|
|
|
close_pair(fdout);
|
2008-02-21 23:42:56 +01:00
|
|
|
else if (cmd->out)
|
|
|
|
close(cmd->out);
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
fail_pipe:
|
|
|
|
error("cannot create pipe for %s: %s",
|
|
|
|
cmd->argv[0], strerror(failed_errno));
|
|
|
|
errno = failed_errno;
|
|
|
|
return -1;
|
2007-10-19 21:47:58 +02:00
|
|
|
}
|
|
|
|
cmd->err = fderr[0];
|
|
|
|
}
|
|
|
|
|
2008-07-07 15:41:34 +02:00
|
|
|
trace_argv_printf(cmd->argv, "trace: run_command:");
|
2011-02-04 09:41:58 +01:00
|
|
|
fflush(NULL);
|
2008-07-07 15:41:34 +02:00
|
|
|
|
2009-09-16 10:20:22 +02:00
|
|
|
#ifndef WIN32
|
2010-01-10 14:11:22 +01:00
|
|
|
{
|
|
|
|
int notify_pipe[2];
|
|
|
|
if (pipe(notify_pipe))
|
|
|
|
notify_pipe[0] = notify_pipe[1] = -1;
|
|
|
|
|
2007-03-10 09:28:05 +01:00
|
|
|
cmd->pid = fork();
|
|
|
|
if (!cmd->pid) {
|
2010-01-10 14:07:52 +01:00
|
|
|
/*
|
|
|
|
* Redirect the channel to write syscall error messages to
|
|
|
|
* before redirecting the process's stderr so that all die()
|
|
|
|
* in subsequent call paths use the parent's stderr.
|
|
|
|
*/
|
|
|
|
if (cmd->no_stderr || need_err) {
|
|
|
|
child_err = dup(2);
|
|
|
|
set_cloexec(child_err);
|
|
|
|
}
|
|
|
|
set_die_routine(die_child);
|
2011-07-27 23:32:34 +02:00
|
|
|
set_error_routine(error_child);
|
2010-01-10 14:07:52 +01:00
|
|
|
|
2010-01-10 14:11:22 +01:00
|
|
|
close(notify_pipe[0]);
|
|
|
|
set_cloexec(notify_pipe[1]);
|
|
|
|
child_notifier = notify_pipe[1];
|
|
|
|
atexit(notify_parent);
|
|
|
|
|
2007-03-12 19:37:55 +01:00
|
|
|
if (cmd->no_stdin)
|
|
|
|
dup_devnull(0);
|
|
|
|
else if (need_in) {
|
2007-03-10 09:28:08 +01:00
|
|
|
dup2(fdin[0], 0);
|
2007-03-12 19:37:28 +01:00
|
|
|
close_pair(fdin);
|
2007-03-10 09:28:08 +01:00
|
|
|
} else if (cmd->in) {
|
|
|
|
dup2(cmd->in, 0);
|
|
|
|
close(cmd->in);
|
2006-12-31 03:55:22 +01:00
|
|
|
}
|
2007-03-10 09:28:08 +01:00
|
|
|
|
2008-03-05 08:35:16 +01:00
|
|
|
if (cmd->no_stderr)
|
|
|
|
dup_devnull(2);
|
|
|
|
else if (need_err) {
|
|
|
|
dup2(fderr[1], 2);
|
|
|
|
close_pair(fderr);
|
2010-02-05 21:57:37 +01:00
|
|
|
} else if (cmd->err > 1) {
|
|
|
|
dup2(cmd->err, 2);
|
|
|
|
close(cmd->err);
|
2008-03-05 08:35:16 +01:00
|
|
|
}
|
|
|
|
|
2007-03-12 19:37:55 +01:00
|
|
|
if (cmd->no_stdout)
|
|
|
|
dup_devnull(1);
|
|
|
|
else if (cmd->stdout_to_stderr)
|
2006-12-31 03:55:19 +01:00
|
|
|
dup2(2, 1);
|
2007-03-12 19:37:45 +01:00
|
|
|
else if (need_out) {
|
|
|
|
dup2(fdout[1], 1);
|
|
|
|
close_pair(fdout);
|
|
|
|
} else if (cmd->out > 1) {
|
|
|
|
dup2(cmd->out, 1);
|
|
|
|
close(cmd->out);
|
|
|
|
}
|
|
|
|
|
2007-05-22 23:48:23 +02:00
|
|
|
if (cmd->dir && chdir(cmd->dir))
|
2009-06-27 17:58:46 +02:00
|
|
|
die_errno("exec '%s': cd to '%s' failed", cmd->argv[0],
|
|
|
|
cmd->dir);
|
2007-05-22 23:48:47 +02:00
|
|
|
if (cmd->env) {
|
2007-05-23 22:21:39 +02:00
|
|
|
for (; *cmd->env; cmd->env++) {
|
|
|
|
if (strchr(*cmd->env, '='))
|
2009-05-01 11:06:36 +02:00
|
|
|
putenv((char *)*cmd->env);
|
2007-05-23 22:21:39 +02:00
|
|
|
else
|
|
|
|
unsetenv(*cmd->env);
|
|
|
|
}
|
2007-05-22 23:48:47 +02:00
|
|
|
}
|
2007-03-10 09:28:00 +01:00
|
|
|
if (cmd->git_cmd) {
|
|
|
|
execv_git_cmd(cmd->argv);
|
2009-12-30 11:53:16 +01:00
|
|
|
} else if (cmd->use_shell) {
|
|
|
|
execv_shell_cmd(cmd->argv);
|
2006-01-11 03:12:17 +01:00
|
|
|
} else {
|
2012-03-30 09:52:18 +02:00
|
|
|
sane_execvp(cmd->argv[0], (char *const*) cmd->argv);
|
2005-12-08 03:04:38 +01:00
|
|
|
}
|
notice error exit from pager
If the pager fails to run, git produces no output, e.g.:
$ GIT_PAGER=not-a-command git log
The error reporting fails for two reasons:
(1) start_command: There is a mechanism that detects errors during
execvp introduced in 2b541bf8 (start_command: detect execvp
failures early). The child writes one byte to a pipe only if
execvp fails. The parent waits for either EOF, when the
successful execvp automatically closes the pipe (see
FD_CLOEXEC in fcntl(1)), or it reads a single byte, in which
case it knows that the execvp failed. This mechanism is
incompatible with the workaround introduced in 35ce8622
(pager: Work around window resizing bug in 'less'), which
waits for input from the parent before the exec. Since both
the parent and the child are waiting for input from each
other, that would result in a deadlock. In order to avoid
that, the mechanism is disabled by closing the child_notifier
file descriptor.
(2) finish_command: The parent correctly detects the 127 exit
status from the child, but the error output goes nowhere,
since by that time it is already being redirected to the
child.
No simple solution for (1) comes to mind.
Number (2) can be solved by not sending error output to the pager.
Not redirecting error output to the pager can result in the pager
overwriting error output with standard output, however.
Since there is no reliable way to handle error reporting in the
parent, produce the output in the child instead.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-01 19:59:21 +02:00
|
|
|
if (errno == ENOENT) {
|
|
|
|
if (!cmd->silent_exec_failure)
|
|
|
|
error("cannot run %s: %s", cmd->argv[0],
|
|
|
|
strerror(ENOENT));
|
2010-01-10 14:07:52 +01:00
|
|
|
exit(127);
|
notice error exit from pager
If the pager fails to run, git produces no output, e.g.:
$ GIT_PAGER=not-a-command git log
The error reporting fails for two reasons:
(1) start_command: There is a mechanism that detects errors during
execvp introduced in 2b541bf8 (start_command: detect execvp
failures early). The child writes one byte to a pipe only if
execvp fails. The parent waits for either EOF, when the
successful execvp automatically closes the pipe (see
FD_CLOEXEC in fcntl(1)), or it reads a single byte, in which
case it knows that the execvp failed. This mechanism is
incompatible with the workaround introduced in 35ce8622
(pager: Work around window resizing bug in 'less'), which
waits for input from the parent before the exec. Since both
the parent and the child are waiting for input from each
other, that would result in a deadlock. In order to avoid
that, the mechanism is disabled by closing the child_notifier
file descriptor.
(2) finish_command: The parent correctly detects the 127 exit
status from the child, but the error output goes nowhere,
since by that time it is already being redirected to the
child.
No simple solution for (1) comes to mind.
Number (2) can be solved by not sending error output to the pager.
Not redirecting error output to the pager can result in the pager
overwriting error output with standard output, however.
Since there is no reliable way to handle error reporting in the
parent, produce the output in the child instead.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-01 19:59:21 +02:00
|
|
|
} else {
|
2010-01-10 14:07:52 +01:00
|
|
|
die_errno("cannot exec '%s'", cmd->argv[0]);
|
notice error exit from pager
If the pager fails to run, git produces no output, e.g.:
$ GIT_PAGER=not-a-command git log
The error reporting fails for two reasons:
(1) start_command: There is a mechanism that detects errors during
execvp introduced in 2b541bf8 (start_command: detect execvp
failures early). The child writes one byte to a pipe only if
execvp fails. The parent waits for either EOF, when the
successful execvp automatically closes the pipe (see
FD_CLOEXEC in fcntl(1)), or it reads a single byte, in which
case it knows that the execvp failed. This mechanism is
incompatible with the workaround introduced in 35ce8622
(pager: Work around window resizing bug in 'less'), which
waits for input from the parent before the exec. Since both
the parent and the child are waiting for input from each
other, that would result in a deadlock. In order to avoid
that, the mechanism is disabled by closing the child_notifier
file descriptor.
(2) finish_command: The parent correctly detects the 127 exit
status from the child, but the error output goes nowhere,
since by that time it is already being redirected to the
child.
No simple solution for (1) comes to mind.
Number (2) can be solved by not sending error output to the pager.
Not redirecting error output to the pager can result in the pager
overwriting error output with standard output, however.
Since there is no reliable way to handle error reporting in the
parent, produce the output in the child instead.
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-01 19:59:21 +02:00
|
|
|
}
|
2005-07-31 21:17:43 +02:00
|
|
|
}
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
if (cmd->pid < 0)
|
|
|
|
error("cannot fork() for %s: %s", cmd->argv[0],
|
|
|
|
strerror(failed_errno = errno));
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
else if (cmd->clean_on_exit)
|
|
|
|
mark_child_for_cleanup(cmd->pid);
|
2010-01-10 14:11:22 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for child's execvp. If the execvp succeeds (or if fork()
|
|
|
|
* failed), EOF is seen immediately by the parent. Otherwise, the
|
|
|
|
* child process sends a single byte.
|
|
|
|
* Note that use of this infrastructure is completely advisory,
|
|
|
|
* therefore, we keep error checks minimal.
|
|
|
|
*/
|
|
|
|
close(notify_pipe[1]);
|
|
|
|
if (read(notify_pipe[0], ¬ify_pipe[1], 1) == 1) {
|
|
|
|
/*
|
|
|
|
* At this point we know that fork() succeeded, but execvp()
|
|
|
|
* failed. Errors have been reported to our stderr.
|
|
|
|
*/
|
2012-11-30 23:40:50 +01:00
|
|
|
wait_or_whine(cmd->pid, cmd->argv[0]);
|
2010-01-10 14:11:22 +01:00
|
|
|
failed_errno = errno;
|
|
|
|
cmd->pid = -1;
|
|
|
|
}
|
|
|
|
close(notify_pipe[0]);
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
|
2010-01-10 14:11:22 +01:00
|
|
|
}
|
2007-12-07 22:08:59 +01:00
|
|
|
#else
|
2009-09-16 10:20:17 +02:00
|
|
|
{
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
int fhin = 0, fhout = 1, fherr = 2;
|
2008-07-28 07:50:28 +02:00
|
|
|
const char **sargv = cmd->argv;
|
2007-12-07 22:08:59 +01:00
|
|
|
char **env = environ;
|
|
|
|
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
if (cmd->no_stdin)
|
|
|
|
fhin = open("/dev/null", O_RDWR);
|
|
|
|
else if (need_in)
|
|
|
|
fhin = dup(fdin[0]);
|
|
|
|
else if (cmd->in)
|
|
|
|
fhin = dup(cmd->in);
|
|
|
|
|
|
|
|
if (cmd->no_stderr)
|
|
|
|
fherr = open("/dev/null", O_RDWR);
|
|
|
|
else if (need_err)
|
|
|
|
fherr = dup(fderr[1]);
|
2010-02-06 06:08:53 +01:00
|
|
|
else if (cmd->err > 2)
|
|
|
|
fherr = dup(cmd->err);
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
|
|
|
|
if (cmd->no_stdout)
|
|
|
|
fhout = open("/dev/null", O_RDWR);
|
|
|
|
else if (cmd->stdout_to_stderr)
|
|
|
|
fhout = dup(fherr);
|
|
|
|
else if (need_out)
|
|
|
|
fhout = dup(fdout[1]);
|
|
|
|
else if (cmd->out > 1)
|
|
|
|
fhout = dup(cmd->out);
|
2007-12-07 22:08:59 +01:00
|
|
|
|
2009-09-11 19:40:08 +02:00
|
|
|
if (cmd->env)
|
|
|
|
env = make_augmented_environ(cmd->env);
|
2007-12-07 22:08:59 +01:00
|
|
|
|
|
|
|
if (cmd->git_cmd) {
|
2008-07-28 07:50:28 +02:00
|
|
|
cmd->argv = prepare_git_cmd(cmd->argv);
|
2009-12-30 11:53:16 +01:00
|
|
|
} else if (cmd->use_shell) {
|
|
|
|
cmd->argv = prepare_shell_cmd(cmd->argv);
|
2007-12-07 22:08:59 +01:00
|
|
|
}
|
|
|
|
|
2010-04-11 22:40:12 +02:00
|
|
|
cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env, cmd->dir,
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
fhin, fhout, fherr);
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
failed_errno = errno;
|
2009-07-04 21:26:42 +02:00
|
|
|
if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
if (cmd->clean_on_exit && cmd->pid >= 0)
|
|
|
|
mark_child_for_cleanup(cmd->pid);
|
2007-12-07 22:08:59 +01:00
|
|
|
|
|
|
|
if (cmd->env)
|
|
|
|
free_environ(env);
|
|
|
|
if (cmd->git_cmd)
|
2008-07-28 07:50:28 +02:00
|
|
|
free(cmd->argv);
|
2007-12-07 22:08:59 +01:00
|
|
|
|
2008-07-28 07:50:28 +02:00
|
|
|
cmd->argv = sargv;
|
Windows: avoid the "dup dance" when spawning a child process
When stdin, stdout, or stderr must be redirected for a child process that
on Windows is spawned using one of the spawn() functions of Microsoft's
C runtime, then there is no choice other than to
1. make a backup copy of fd 0,1,2 with dup
2. dup2 the redirection source fd into 0,1,2
3. spawn
4. dup2 the backup back into 0,1,2
5. close the backup copy and the redirection source
We used this idiom as well -- but we are not using the spawn() functions
anymore!
Instead, we have our own implementation. We had hardcoded that stdin,
stdout, and stderr of the child process were inherited from the parent's
fds 0, 1, and 2. But we can actually specify any fd.
With this patch, the fds to inherit are passed from start_command()'s
WIN32 section to our spawn implementation. This way, we can avoid the
backup copies of the fds.
The backup copies were a bug waiting to surface: The OS handles underlying
the dup()ed fds were inherited by the child process (but were not
associated with a file descriptor in the child). Consequently, the file or
pipe represented by the OS handle remained open even after the backup copy
was closed in the parent process until the child exited.
Since our implementation of pipe() creates non-inheritable OS handles, we
still dup() file descriptors in start_command() because dup() happens to
create inheritable duplicates. (A nice side effect is that the fd cleanup
in start_command is the same for Windows and Unix and remains unchanged.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-15 21:12:18 +01:00
|
|
|
if (fhin != 0)
|
|
|
|
close(fhin);
|
|
|
|
if (fhout != 1)
|
|
|
|
close(fhout);
|
|
|
|
if (fherr != 2)
|
|
|
|
close(fherr);
|
2009-09-16 10:20:17 +02:00
|
|
|
}
|
2007-12-07 22:08:59 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (cmd->pid < 0) {
|
|
|
|
if (need_in)
|
|
|
|
close_pair(fdin);
|
|
|
|
else if (cmd->in)
|
|
|
|
close(cmd->in);
|
|
|
|
if (need_out)
|
|
|
|
close_pair(fdout);
|
|
|
|
else if (cmd->out)
|
|
|
|
close(cmd->out);
|
|
|
|
if (need_err)
|
|
|
|
close_pair(fderr);
|
2010-05-20 20:57:52 +02:00
|
|
|
else if (cmd->err)
|
|
|
|
close(cmd->err);
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
errno = failed_errno;
|
|
|
|
return -1;
|
2007-12-07 22:08:59 +01:00
|
|
|
}
|
2007-03-10 09:28:08 +01:00
|
|
|
|
|
|
|
if (need_in)
|
|
|
|
close(fdin[0]);
|
|
|
|
else if (cmd->in)
|
|
|
|
close(cmd->in);
|
|
|
|
|
2007-03-12 19:37:45 +01:00
|
|
|
if (need_out)
|
|
|
|
close(fdout[1]);
|
2008-02-21 23:42:56 +01:00
|
|
|
else if (cmd->out)
|
2007-03-12 19:37:45 +01:00
|
|
|
close(cmd->out);
|
|
|
|
|
2007-10-19 21:47:58 +02:00
|
|
|
if (need_err)
|
|
|
|
close(fderr[1]);
|
2010-02-05 21:57:37 +01:00
|
|
|
else if (cmd->err)
|
|
|
|
close(cmd->err);
|
2007-10-19 21:47:58 +02:00
|
|
|
|
2007-03-10 09:28:05 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-19 21:48:00 +02:00
|
|
|
int finish_command(struct child_process *cmd)
|
|
|
|
{
|
2012-11-30 23:40:50 +01:00
|
|
|
return wait_or_whine(cmd->pid, cmd->argv[0]);
|
2007-10-19 21:48:00 +02:00
|
|
|
}
|
|
|
|
|
2007-03-10 09:28:05 +01:00
|
|
|
int run_command(struct child_process *cmd)
|
|
|
|
{
|
|
|
|
int code = start_command(cmd);
|
|
|
|
if (code)
|
|
|
|
return code;
|
|
|
|
return finish_command(cmd);
|
|
|
|
}
|
|
|
|
|
2007-05-22 23:48:23 +02:00
|
|
|
static void prepare_run_command_v_opt(struct child_process *cmd,
|
2007-05-22 23:48:47 +02:00
|
|
|
const char **argv,
|
|
|
|
int opt)
|
2007-05-22 23:48:23 +02:00
|
|
|
{
|
|
|
|
memset(cmd, 0, sizeof(*cmd));
|
|
|
|
cmd->argv = 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;
|
2009-07-04 21:26:42 +02:00
|
|
|
cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
|
2009-12-30 11:53:16 +01:00
|
|
|
cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
|
2012-01-08 21:41:09 +01:00
|
|
|
cmd->clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0;
|
2007-05-22 23:48:23 +02:00
|
|
|
}
|
|
|
|
|
2007-03-10 09:28:00 +01:00
|
|
|
int run_command_v_opt(const char **argv, int opt)
|
|
|
|
{
|
|
|
|
struct child_process cmd;
|
2007-05-22 23:48:23 +02:00
|
|
|
prepare_run_command_v_opt(&cmd, argv, opt);
|
|
|
|
return run_command(&cmd);
|
|
|
|
}
|
|
|
|
|
2007-05-22 23:48:47 +02:00
|
|
|
int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
|
|
|
|
{
|
|
|
|
struct child_process cmd;
|
|
|
|
prepare_run_command_v_opt(&cmd, argv, opt);
|
|
|
|
cmd.dir = dir;
|
|
|
|
cmd.env = env;
|
|
|
|
return run_command(&cmd);
|
|
|
|
}
|
2007-10-19 21:48:00 +02:00
|
|
|
|
2010-03-09 21:00:36 +01:00
|
|
|
#ifndef NO_PTHREADS
|
Dying in an async procedure should only exit the thread, not the process.
Async procedures are intended as helpers that perform a very restricted
task, and the caller usually has to manage them in a larger context.
Conceptually, the async procedure is not concerned with the "bigger
picture" in whose context it is run. When it dies, it is not supposed
to destroy this "bigger picture", but rather only its own limit view
of the world. On POSIX, the async procedure is run in its own process,
and exiting this process naturally had only these limited effects.
On Windows (or when ASYNC_AS_THREAD is set), calling die() exited the
whole process, destroying the caller (the "big picture") as well.
This fixes it to exit only the thread.
Without ASYNC_AS_THREAD, one particular effect of exiting the async
procedure process is that it automatically closes file descriptors, most
notably the writable end of the pipe that the async procedure writes to.
The async API already requires that the async procedure closes the pipe
ends when it exits normally. But for calls to die() no requirements are
imposed. In the non-threaded case the pipe ends are closed implicitly
by the exiting process, but in the threaded case, the die routine must
take care of closing them.
Now t5530-upload-pack-error.sh passes on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-06 16:40:43 +01:00
|
|
|
static pthread_t main_thread;
|
|
|
|
static int main_thread_set;
|
|
|
|
static pthread_key_t async_key;
|
|
|
|
|
2010-03-06 16:40:42 +01:00
|
|
|
static void *run_thread(void *data)
|
2007-12-08 22:19:14 +01:00
|
|
|
{
|
|
|
|
struct async *async = data;
|
2010-03-09 21:00:36 +01:00
|
|
|
intptr_t ret;
|
Dying in an async procedure should only exit the thread, not the process.
Async procedures are intended as helpers that perform a very restricted
task, and the caller usually has to manage them in a larger context.
Conceptually, the async procedure is not concerned with the "bigger
picture" in whose context it is run. When it dies, it is not supposed
to destroy this "bigger picture", but rather only its own limit view
of the world. On POSIX, the async procedure is run in its own process,
and exiting this process naturally had only these limited effects.
On Windows (or when ASYNC_AS_THREAD is set), calling die() exited the
whole process, destroying the caller (the "big picture") as well.
This fixes it to exit only the thread.
Without ASYNC_AS_THREAD, one particular effect of exiting the async
procedure process is that it automatically closes file descriptors, most
notably the writable end of the pipe that the async procedure writes to.
The async API already requires that the async procedure closes the pipe
ends when it exits normally. But for calls to die() no requirements are
imposed. In the non-threaded case the pipe ends are closed implicitly
by the exiting process, but in the threaded case, the die routine must
take care of closing them.
Now t5530-upload-pack-error.sh passes on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-06 16:40:43 +01:00
|
|
|
|
|
|
|
pthread_setspecific(async_key, async);
|
2010-03-09 21:00:36 +01:00
|
|
|
ret = async->proc(async->proc_in, async->proc_out, async->data);
|
2010-03-06 16:40:42 +01:00
|
|
|
return (void *)ret;
|
2007-12-08 22:19:14 +01:00
|
|
|
}
|
Dying in an async procedure should only exit the thread, not the process.
Async procedures are intended as helpers that perform a very restricted
task, and the caller usually has to manage them in a larger context.
Conceptually, the async procedure is not concerned with the "bigger
picture" in whose context it is run. When it dies, it is not supposed
to destroy this "bigger picture", but rather only its own limit view
of the world. On POSIX, the async procedure is run in its own process,
and exiting this process naturally had only these limited effects.
On Windows (or when ASYNC_AS_THREAD is set), calling die() exited the
whole process, destroying the caller (the "big picture") as well.
This fixes it to exit only the thread.
Without ASYNC_AS_THREAD, one particular effect of exiting the async
procedure process is that it automatically closes file descriptors, most
notably the writable end of the pipe that the async procedure writes to.
The async API already requires that the async procedure closes the pipe
ends when it exits normally. But for calls to die() no requirements are
imposed. In the non-threaded case the pipe ends are closed implicitly
by the exiting process, but in the threaded case, the die routine must
take care of closing them.
Now t5530-upload-pack-error.sh passes on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-06 16:40:43 +01:00
|
|
|
|
|
|
|
static NORETURN void die_async(const char *err, va_list params)
|
|
|
|
{
|
|
|
|
vreportf("fatal: ", err, params);
|
|
|
|
|
|
|
|
if (!pthread_equal(main_thread, pthread_self())) {
|
|
|
|
struct async *async = pthread_getspecific(async_key);
|
|
|
|
if (async->proc_in >= 0)
|
|
|
|
close(async->proc_in);
|
|
|
|
if (async->proc_out >= 0)
|
|
|
|
close(async->proc_out);
|
|
|
|
pthread_exit((void *)128);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit(128);
|
2007-12-08 22:19:14 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-19 21:48:00 +02:00
|
|
|
int start_async(struct async *async)
|
|
|
|
{
|
2010-02-05 21:57:38 +01:00
|
|
|
int need_in, need_out;
|
|
|
|
int fdin[2], fdout[2];
|
|
|
|
int proc_in, proc_out;
|
2007-10-19 21:48:00 +02:00
|
|
|
|
2010-02-05 21:57:38 +01:00
|
|
|
need_in = async->in < 0;
|
|
|
|
if (need_in) {
|
|
|
|
if (pipe(fdin) < 0) {
|
|
|
|
if (async->out > 0)
|
|
|
|
close(async->out);
|
|
|
|
return error("cannot create pipe: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
async->in = fdin[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
need_out = async->out < 0;
|
|
|
|
if (need_out) {
|
|
|
|
if (pipe(fdout) < 0) {
|
|
|
|
if (need_in)
|
|
|
|
close_pair(fdin);
|
|
|
|
else if (async->in)
|
|
|
|
close(async->in);
|
|
|
|
return error("cannot create pipe: %s", strerror(errno));
|
|
|
|
}
|
|
|
|
async->out = fdout[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_in)
|
|
|
|
proc_in = fdin[0];
|
|
|
|
else if (async->in)
|
|
|
|
proc_in = async->in;
|
|
|
|
else
|
|
|
|
proc_in = -1;
|
|
|
|
|
|
|
|
if (need_out)
|
|
|
|
proc_out = fdout[1];
|
|
|
|
else if (async->out)
|
|
|
|
proc_out = async->out;
|
|
|
|
else
|
|
|
|
proc_out = -1;
|
2007-10-19 21:48:00 +02:00
|
|
|
|
2010-03-09 21:00:36 +01:00
|
|
|
#ifdef NO_PTHREADS
|
2008-08-04 02:30:03 +02:00
|
|
|
/* Flush stdio before fork() to avoid cloning buffers */
|
|
|
|
fflush(NULL);
|
|
|
|
|
2007-10-19 21:48:00 +02:00
|
|
|
async->pid = fork();
|
|
|
|
if (async->pid < 0) {
|
|
|
|
error("fork (async) failed: %s", strerror(errno));
|
2010-02-05 21:57:38 +01:00
|
|
|
goto error;
|
2007-10-19 21:48:00 +02:00
|
|
|
}
|
|
|
|
if (!async->pid) {
|
2010-02-05 21:57:38 +01:00
|
|
|
if (need_in)
|
|
|
|
close(fdin[1]);
|
|
|
|
if (need_out)
|
|
|
|
close(fdout[0]);
|
|
|
|
exit(!!async->proc(proc_in, proc_out, async->data));
|
2007-10-19 21:48:00 +02:00
|
|
|
}
|
2010-02-05 21:57:38 +01:00
|
|
|
|
run-command: optionally kill children on exit
When we spawn a helper process, it should generally be done
and finish_command called before we exit. However, if we
exit abnormally due to an early return or a signal, the
helper may continue to run in our absence.
In the best case, this may simply be wasted CPU cycles or a
few stray messages on a terminal. But it could also mean a
process that the user thought was aborted continues to run
to completion (e.g., a push's pack-objects helper will
complete the push, even though you killed the push process).
This patch provides infrastructure for run-command to keep
track of PIDs to be killed, and clean them on signal
reception or input, just as we do with tempfiles. PIDs can
be added in two ways:
1. If NO_PTHREADS is defined, async helper processes are
automatically marked. By definition this code must be
ready to die when the parent dies, since it may be
implemented as a thread of the parent process.
2. If the run-command caller specifies the "clean_on_exit"
option. This is not the default, as there are cases
where it is OK for the child to outlive us (e.g., when
spawning a pager).
PIDs are cleared from the kill-list automatically during
wait_or_whine, which is called from finish_command and
finish_async.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-07 12:42:43 +01:00
|
|
|
mark_child_for_cleanup(async->pid);
|
|
|
|
|
2010-02-05 21:57:38 +01:00
|
|
|
if (need_in)
|
|
|
|
close(fdin[0]);
|
|
|
|
else if (async->in)
|
|
|
|
close(async->in);
|
|
|
|
|
|
|
|
if (need_out)
|
|
|
|
close(fdout[1]);
|
|
|
|
else if (async->out)
|
|
|
|
close(async->out);
|
2007-12-08 22:19:14 +01:00
|
|
|
#else
|
Dying in an async procedure should only exit the thread, not the process.
Async procedures are intended as helpers that perform a very restricted
task, and the caller usually has to manage them in a larger context.
Conceptually, the async procedure is not concerned with the "bigger
picture" in whose context it is run. When it dies, it is not supposed
to destroy this "bigger picture", but rather only its own limit view
of the world. On POSIX, the async procedure is run in its own process,
and exiting this process naturally had only these limited effects.
On Windows (or when ASYNC_AS_THREAD is set), calling die() exited the
whole process, destroying the caller (the "big picture") as well.
This fixes it to exit only the thread.
Without ASYNC_AS_THREAD, one particular effect of exiting the async
procedure process is that it automatically closes file descriptors, most
notably the writable end of the pipe that the async procedure writes to.
The async API already requires that the async procedure closes the pipe
ends when it exits normally. But for calls to die() no requirements are
imposed. In the non-threaded case the pipe ends are closed implicitly
by the exiting process, but in the threaded case, the die routine must
take care of closing them.
Now t5530-upload-pack-error.sh passes on Windows.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-03-06 16:40:43 +01:00
|
|
|
if (!main_thread_set) {
|
|
|
|
/*
|
|
|
|
* We assume that the first time that start_async is called
|
|
|
|
* it is from the main thread.
|
|
|
|
*/
|
|
|
|
main_thread_set = 1;
|
|
|
|
main_thread = pthread_self();
|
|
|
|
pthread_key_create(&async_key, NULL);
|
|
|
|
set_die_routine(die_async);
|
|
|
|
}
|
|
|
|
|
2010-03-06 16:40:42 +01:00
|
|
|
if (proc_in >= 0)
|
|
|
|
set_cloexec(proc_in);
|
|
|
|
if (proc_out >= 0)
|
|
|
|
set_cloexec(proc_out);
|
2010-02-05 21:57:38 +01:00
|
|
|
async->proc_in = proc_in;
|
|
|
|
async->proc_out = proc_out;
|
2010-03-06 16:40:42 +01:00
|
|
|
{
|
|
|
|
int err = pthread_create(&async->tid, NULL, run_thread, async);
|
|
|
|
if (err) {
|
|
|
|
error("cannot create thread: %s", strerror(err));
|
|
|
|
goto error;
|
|
|
|
}
|
2007-12-08 22:19:14 +01:00
|
|
|
}
|
|
|
|
#endif
|
2007-10-19 21:48:00 +02:00
|
|
|
return 0;
|
2010-02-05 21:57:38 +01:00
|
|
|
|
|
|
|
error:
|
|
|
|
if (need_in)
|
|
|
|
close_pair(fdin);
|
|
|
|
else if (async->in)
|
|
|
|
close(async->in);
|
|
|
|
|
|
|
|
if (need_out)
|
|
|
|
close_pair(fdout);
|
|
|
|
else if (async->out)
|
|
|
|
close(async->out);
|
|
|
|
return -1;
|
2007-10-19 21:48:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int finish_async(struct async *async)
|
|
|
|
{
|
2010-03-09 21:00:36 +01:00
|
|
|
#ifdef NO_PTHREADS
|
2010-03-06 16:40:42 +01:00
|
|
|
return wait_or_whine(async->pid, "child process", 0);
|
2007-12-08 22:19:14 +01:00
|
|
|
#else
|
2010-03-06 16:40:42 +01:00
|
|
|
void *ret = (void *)(intptr_t)(-1);
|
|
|
|
|
|
|
|
if (pthread_join(async->tid, &ret))
|
|
|
|
error("pthread_join failed");
|
|
|
|
return (int)(intptr_t)ret;
|
2007-12-08 22:19:14 +01:00
|
|
|
#endif
|
2007-10-19 21:48:00 +02:00
|
|
|
}
|
2009-01-16 20:09:59 +01:00
|
|
|
|
|
|
|
int run_hook(const char *index_file, const char *name, ...)
|
|
|
|
{
|
|
|
|
struct child_process hook;
|
2011-09-13 23:58:25 +02:00
|
|
|
struct argv_array argv = ARGV_ARRAY_INIT;
|
|
|
|
const char *p, *env[2];
|
2009-01-16 20:09:59 +01:00
|
|
|
char index[PATH_MAX];
|
|
|
|
va_list args;
|
|
|
|
int ret;
|
|
|
|
|
2009-01-16 20:10:01 +01:00
|
|
|
if (access(git_path("hooks/%s", name), X_OK) < 0)
|
|
|
|
return 0;
|
|
|
|
|
2009-01-16 20:09:59 +01:00
|
|
|
va_start(args, name);
|
2011-09-13 23:58:25 +02:00
|
|
|
argv_array_push(&argv, git_path("hooks/%s", name));
|
|
|
|
while ((p = va_arg(args, const char *)))
|
|
|
|
argv_array_push(&argv, p);
|
2009-01-16 20:09:59 +01:00
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
memset(&hook, 0, sizeof(hook));
|
2011-09-13 23:58:25 +02:00
|
|
|
hook.argv = argv.argv;
|
2009-01-16 20:09:59 +01:00
|
|
|
hook.no_stdin = 1;
|
|
|
|
hook.stdout_to_stderr = 1;
|
|
|
|
if (index_file) {
|
|
|
|
snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
|
|
|
|
env[0] = index;
|
|
|
|
env[1] = NULL;
|
|
|
|
hook.env = env;
|
|
|
|
}
|
|
|
|
|
run_command: report system call errors instead of returning error codes
The motivation for this change is that system call failures are serious
errors that should be reported to the user, but only few callers took the
burden to decode the error codes that the functions returned into error
messages.
If at all, then only an unspecific error message was given. A prominent
example is this:
$ git upload-pack . | :
fatal: unable to run 'git-upload-pack'
In this example, git-upload-pack, the external command invoked through the
git wrapper, dies due to SIGPIPE, but the git wrapper does not bother to
report the real cause. In fact, this very error message is copied to the
syslog if git-daemon's client aborts the connection early.
With this change, system call failures are reported immediately after the
failure and only a generic failure code is returned to the caller. In the
above example the error is now to the point:
$ git upload-pack . | :
error: git-upload-pack died of signal
Note that there is no error report if the invoked program terminated with
a non-zero exit code, because it is reasonable to expect that the invoked
program has already reported an error. (But many run_command call sites
nevertheless write a generic error message.)
There was one special return code that was used to identify the case where
run_command failed because the requested program could not be exec'd. This
special case is now treated like a system call failure with errno set to
ENOENT. No error is reported in this case, because the call site in git.c
expects this as a normal result. Therefore, the callers that carefully
decoded the return value still check for this condition.
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-07-04 21:26:40 +02:00
|
|
|
ret = run_command(&hook);
|
2011-09-13 23:58:25 +02:00
|
|
|
argv_array_clear(&argv);
|
2009-01-16 20:09:59 +01:00
|
|
|
return ret;
|
|
|
|
}
|