Dying in an async procedure should only exit the thread, not the process.
[gitweb.git] / run-command.c
index 77aefff2e27e369feffccbad817845af17597b02..66cc4bfa57b0fa8378a5d1f8562462db1d3c2078 100644 (file)
@@ -448,12 +448,35 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
 }
 
 #ifdef ASYNC_AS_THREAD
+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;
+
+       pthread_setspecific(async_key, async);
+
        intptr_t 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)
@@ -525,6 +548,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)