t/t7005-editor: change from skip_all=* to prereq skip
[gitweb.git] / run-command.c
index 77aefff2e27e369feffccbad817845af17597b02..2a1041ef6599c84fff6a8d9faf5dea23a2af3ab0 100644 (file)
@@ -67,19 +67,21 @@ static int child_notifier = -1;
 
 static void notify_parent(void)
 {
-       write(child_notifier, "", 1);
+       ssize_t unused;
+       unused = write(child_notifier, "", 1);
 }
 
 static NORETURN void die_child(const char *err, va_list params)
 {
        char msg[4096];
+       ssize_t unused;
        int len = vsnprintf(msg, sizeof(msg), err, params);
        if (len > sizeof(msg))
                len = sizeof(msg);
 
-       write(child_err, "fatal: ", 7);
-       write(child_err, msg, len);
-       write(child_err, "\n", 1);
+       unused = write(child_err, "fatal: ", 7);
+       unused = write(child_err, msg, len);
+       unused = write(child_err, "\n", 1);
        exit(128);
 }
 #endif
@@ -340,8 +342,6 @@ int start_command(struct child_process *cmd)
        else if (cmd->out > 1)
                fhout = dup(cmd->out);
 
-       if (cmd->dir)
-               die("chdir in start_command() not implemented");
        if (cmd->env)
                env = make_augmented_environ(cmd->env);
 
@@ -351,7 +351,7 @@ int start_command(struct child_process *cmd)
                cmd->argv = prepare_shell_cmd(cmd->argv);
        }
 
-       cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env,
+       cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env, cmd->dir,
                                  fhin, fhout, fherr);
        failed_errno = errno;
        if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
@@ -383,6 +383,8 @@ int start_command(struct child_process *cmd)
                        close(cmd->out);
                if (need_err)
                        close_pair(fderr);
+               else if (cmd->err)
+                       close(cmd->err);
                errno = failed_errno;
                return -1;
        }
@@ -447,13 +449,36 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
        return run_command(&cmd);
 }
 
-#ifdef ASYNC_AS_THREAD
+#ifndef NO_PTHREADS
+static pthread_t main_thread;
+static int main_thread_set;
+static pthread_key_t async_key;
+
 static void *run_thread(void *data)
 {
        struct async *async = data;
-       intptr_t ret = async->proc(async->proc_in, async->proc_out, async->data);
+       intptr_t ret;
+
+       pthread_setspecific(async_key, async);
+       ret = async->proc(async->proc_in, async->proc_out, async->data);
        return (void *)ret;
 }
+
+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);
+}
 #endif
 
 int start_async(struct async *async)
@@ -498,7 +523,7 @@ int start_async(struct async *async)
        else
                proc_out = -1;
 
-#ifndef ASYNC_AS_THREAD
+#ifdef NO_PTHREADS
        /* Flush stdio before fork() to avoid cloning buffers */
        fflush(NULL);
 
@@ -525,6 +550,17 @@ int start_async(struct async *async)
        else if (async->out)
                close(async->out);
 #else
+       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);
+       }
+
        if (proc_in >= 0)
                set_cloexec(proc_in);
        if (proc_out >= 0)
@@ -556,7 +592,7 @@ int start_async(struct async *async)
 
 int finish_async(struct async *async)
 {
-#ifndef ASYNC_AS_THREAD
+#ifdef NO_PTHREADS
        return wait_or_whine(async->pid, "child process", 0);
 #else
        void *ret = (void *)(intptr_t)(-1);