From 85763c86da5f0826a879f37056f2de033cb5ca12 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 16 Nov 2007 13:46:37 +0100 Subject: [PATCH] Implement thread-specific die() routines; use one in start_async(). --- run-command.c | 16 ++++++++++++++++ t/Makefile | 3 --- usage.c | 32 +++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/run-command.c b/run-command.c index b05c734d05..09725b983f 100644 --- a/run-command.c +++ b/run-command.c @@ -293,9 +293,22 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const } #ifdef __MINGW32__ +static int close_fd = -1; +NORETURN void die_from_thread(const char *err, va_list params) +{ + vreport("fatal: ", err, params); + if (close_fd >= 0) + close(close_fd); + _endthreadex(128); + exit(128); /* silence compiler */ +} + static __stdcall unsigned run_thread(void *data) { struct async *async = data; + close_fd = async->fd_for_proc; + extern NORETURN void die_from_thread(const char *err, va_list params); + set_die_routine(die_from_thread); return async->proc(async->fd_for_proc, async->data); } #endif @@ -349,6 +362,9 @@ int finish_async(struct async *async) else if (!GetExitCodeThread(async->tid, &ret)) ret = error("cannot get thread exit code: %lu", GetLastError()); CloseHandle(async->tid); + if (ret) + /* test suite tests for this string */ + error("waitpid (async) failed"); #endif return ret; } diff --git a/t/Makefile b/t/Makefile index a0ed388ba5..9af58b9bc6 100644 --- a/t/Makefile +++ b/t/Makefile @@ -48,9 +48,6 @@ valgrind: GIT_SKIP_TESTS := $(GIT_SKIP_TESTS_LOCAL) # git am does not treat absolute path to mbox file correctly GIT_SKIP_TESTS += t4150.18 -# git upload-pack does not write an error message in this case -# (reason unknown; seems to be a race condition) -GIT_SKIP_TESTS += t5530.6 # output contains CRLF (I think) GIT_SKIP_TESTS += t7401.14 # output contains CRLF (I think) diff --git a/usage.c b/usage.c index 349f3fb350..9e35e8a390 100644 --- a/usage.c +++ b/usage.c @@ -34,16 +34,38 @@ static void warn_builtin(const char *warn, va_list params) vreport("warning: ", warn, params); } +typedef void (*die_fn_t)(const char *err, va_list params) NORETURN; + +static DWORD tls_index; + +static void tls_init(void) __attribute__((constructor)); +static void tls_init(void) +{ + tls_index = TlsAlloc(); +} + +struct routines { + die_fn_t die_routine; +}; /* If we are in a dlopen()ed .so write to a global variable would segfault * (ugh), so keep things static. */ static void (*usage_routine)(const char *err) NORETURN = usage_builtin; -static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin; static void (*error_routine)(const char *err, va_list params) = error_builtin; static void (*warn_routine)(const char *err, va_list params) = warn_builtin; void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN) { - die_routine = routine; + struct routines *r = TlsGetValue(tls_index); + if (r == NULL) { + /* avoid die()! */ + r = calloc(sizeof(*r), 1); + if (r == NULL) { + fprintf(stderr, "cannot allocate thread-local storage"); + return; + } + TlsSetValue(tls_index, r); + } + r->die_routine = routine; } void usage(const char *err) @@ -54,9 +76,13 @@ void usage(const char *err) void die(const char *err, ...) { va_list params; + struct routines *r = TlsGetValue(tls_index); va_start(params, err); - die_routine(err, params); + if (r == NULL || r->die_routine == NULL) + die_builtin(err, params); + else + r->die_routine(err, params); va_end(params); }