t9118-git-svn-funky-branch-names.sh: use the $( ... ) construct for command substitution
[gitweb.git] / run-command.c
index fc391fb9cdd6977e8e40d00d2c6142fb824f99d1..13fa452e8c3d5a5e20e24a969d53ce7ade4019bf 100644 (file)
@@ -24,26 +24,27 @@ struct child_to_clean {
 static struct child_to_clean *children_to_clean;
 static int installed_child_cleanup_handler;
 
-static void cleanup_children(int sig)
+static void cleanup_children(int sig, int in_signal)
 {
        while (children_to_clean) {
                struct child_to_clean *p = children_to_clean;
                children_to_clean = p->next;
                kill(p->pid, sig);
-               free(p);
+               if (!in_signal)
+                       free(p);
        }
 }
 
 static void cleanup_children_on_signal(int sig)
 {
-       cleanup_children(sig);
+       cleanup_children(sig, 1);
        sigchain_pop(sig);
        raise(sig);
 }
 
 static void cleanup_children_on_exit(void)
 {
-       cleanup_children(SIGTERM);
+       cleanup_children(SIGTERM, 0);
 }
 
 static void mark_child_for_cleanup(pid_t pid)
@@ -206,7 +207,6 @@ static int execv_shell_cmd(const char **argv)
 #endif
 
 #ifndef GIT_WINDOWS_NATIVE
-static int child_err = 2;
 static int child_notifier = -1;
 
 static void notify_parent(void)
@@ -218,17 +218,6 @@ static void notify_parent(void)
         */
        xwrite(child_notifier, "", 1);
 }
-
-static NORETURN void die_child(const char *err, va_list params)
-{
-       vwritef(child_err, "fatal: ", err, params);
-       exit(128);
-}
-
-static void error_child(const char *err, va_list params)
-{
-       vwritef(child_err, "error: ", err, params);
-}
 #endif
 
 static inline void set_cloexec(int fd)
@@ -238,7 +227,7 @@ static inline void set_cloexec(int fd)
                fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
 }
 
-static int wait_or_whine(pid_t pid, const char *argv0)
+static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
 {
        int status, code = -1;
        pid_t waiting;
@@ -246,6 +235,8 @@ static int wait_or_whine(pid_t pid, const char *argv0)
 
        while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
                ;       /* nothing */
+       if (in_signal)
+               return 0;
 
        if (waiting < 0) {
                failed_errno = errno;
@@ -367,11 +358,10 @@ int start_command(struct child_process *cmd)
                 * in subsequent call paths use the parent's stderr.
                 */
                if (cmd->no_stderr || need_err) {
-                       child_err = dup(2);
+                       int child_err = dup(2);
                        set_cloexec(child_err);
+                       set_error_handle(fdopen(child_err, "w"));
                }
-               set_die_routine(die_child);
-               set_error_routine(error_child);
 
                close(notify_pipe[0]);
                set_cloexec(notify_pipe[1]);
@@ -455,7 +445,7 @@ int start_command(struct child_process *cmd)
                 * At this point we know that fork() succeeded, but execvp()
                 * failed. Errors have been reported to our stderr.
                 */
-               wait_or_whine(cmd->pid, cmd->argv[0]);
+               wait_or_whine(cmd->pid, cmd->argv[0], 0);
                failed_errno = errno;
                cmd->pid = -1;
        }
@@ -553,11 +543,17 @@ int start_command(struct child_process *cmd)
 
 int finish_command(struct child_process *cmd)
 {
-       int ret = wait_or_whine(cmd->pid, cmd->argv[0]);
+       int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
        child_process_clear(cmd);
        return ret;
 }
 
+int finish_command_in_signal(struct child_process *cmd)
+{
+       return wait_or_whine(cmd->pid, cmd->argv[0], 1);
+}
+
+
 int run_command(struct child_process *cmd)
 {
        int code;
@@ -611,7 +607,7 @@ static NORETURN void die_async(const char *err, va_list params)
 {
        vreportf("fatal: ", err, params);
 
-       if (!pthread_equal(main_thread, pthread_self())) {
+       if (in_async()) {
                struct async *async = pthread_getspecific(async_key);
                if (async->proc_in >= 0)
                        close(async->proc_in);
@@ -630,6 +626,13 @@ static int async_die_is_recursing(void)
        return ret != NULL;
 }
 
+int in_async(void)
+{
+       if (!main_thread_set)
+               return 0; /* no asyncs started yet */
+       return !pthread_equal(main_thread, pthread_self());
+}
+
 #else
 
 static struct {
@@ -669,6 +672,12 @@ int git_atexit(void (*handler)(void))
 }
 #define atexit git_atexit
 
+static int process_is_async;
+int in_async(void)
+{
+       return process_is_async;
+}
+
 #endif
 
 int start_async(struct async *async)
@@ -728,6 +737,7 @@ int start_async(struct async *async)
                if (need_out)
                        close(fdout[0]);
                git_atexit_clear();
+               process_is_async = 1;
                exit(!!async->proc(proc_in, proc_out, async->data));
        }
 
@@ -788,7 +798,7 @@ int start_async(struct async *async)
 int finish_async(struct async *async)
 {
 #ifdef NO_PTHREADS
-       return wait_or_whine(async->pid, "child process");
+       return wait_or_whine(async->pid, "child process", 0);
 #else
        void *ret = (void *)(intptr_t)(-1);
 
@@ -798,13 +808,15 @@ int finish_async(struct async *async)
 #endif
 }
 
-char *find_hook(const char *name)
+const char *find_hook(const char *name)
 {
-       char *path = git_path("hooks/%s", name);
-       if (access(path, X_OK) < 0)
-               path = NULL;
+       static struct strbuf path = STRBUF_INIT;
 
-       return path;
+       strbuf_reset(&path);
+       strbuf_git_path(&path, "hooks/%s", name);
+       if (access(path.buf, X_OK) < 0)
+               return NULL;
+       return path.buf;
 }
 
 int run_hook_ve(const char *const *env, const char *name, va_list args)