Implement thread-specific die() routines; use one in start_async().

This commit is contained in:
Johannes Sixt
2007-11-16 13:46:37 +01:00
committed by Johannes Sixt
parent 4eb0463971
commit 85763c86da
3 changed files with 45 additions and 6 deletions

View File

@@ -293,9 +293,22 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
} }
#ifdef __MINGW32__ #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) static __stdcall unsigned run_thread(void *data)
{ {
struct async *async = 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); return async->proc(async->fd_for_proc, async->data);
} }
#endif #endif
@@ -349,6 +362,9 @@ int finish_async(struct async *async)
else if (!GetExitCodeThread(async->tid, &ret)) else if (!GetExitCodeThread(async->tid, &ret))
ret = error("cannot get thread exit code: %lu", GetLastError()); ret = error("cannot get thread exit code: %lu", GetLastError());
CloseHandle(async->tid); CloseHandle(async->tid);
if (ret)
/* test suite tests for this string */
error("waitpid (async) failed");
#endif #endif
return ret; return ret;
} }

View File

@@ -48,9 +48,6 @@ valgrind:
GIT_SKIP_TESTS := $(GIT_SKIP_TESTS_LOCAL) GIT_SKIP_TESTS := $(GIT_SKIP_TESTS_LOCAL)
# git am does not treat absolute path to mbox file correctly # git am does not treat absolute path to mbox file correctly
GIT_SKIP_TESTS += t4150.18 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) # output contains CRLF (I think)
GIT_SKIP_TESTS += t7401.14 GIT_SKIP_TESTS += t7401.14
# output contains CRLF (I think) # output contains CRLF (I think)

32
usage.c
View File

@@ -34,16 +34,38 @@ static void warn_builtin(const char *warn, va_list params)
vreport("warning: ", warn, 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 /* If we are in a dlopen()ed .so write to a global variable would segfault
* (ugh), so keep things static. */ * (ugh), so keep things static. */
static void (*usage_routine)(const char *err) NORETURN = usage_builtin; 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 (*error_routine)(const char *err, va_list params) = error_builtin;
static void (*warn_routine)(const char *err, va_list params) = warn_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) 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) void usage(const char *err)
@@ -54,9 +76,13 @@ void usage(const char *err)
void die(const char *err, ...) void die(const char *err, ...)
{ {
va_list params; va_list params;
struct routines *r = TlsGetValue(tls_index);
va_start(params, err); 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); va_end(params);
} }