From bedf81eb994a1cd88473e37babcdb336e6444ff8 Mon Sep 17 00:00:00 2001 From: Lénaïc Huard Date: Wed, 17 Feb 2010 21:35:18 +0100 Subject: Implement a mutex free version of backtrace() The glibc version of backtrace() uses a mutex which is also used by C++ exception throwing. Using it in mutrace leads to dead lock when a C++ exception throws. --- configure.ac | 2 +- mutrace.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 462be86..5cf6999 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ AC_USE_SYSTEM_EXTENSIONS AC_PROG_CXX # GCC flags -CC_CHECK_CFLAGS_APPEND([-Wall -W -Wextra -pipe -Wno-long-long -Winline -Wvla -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wno-strict-aliasing -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common -fdiagnostics-show-option]) +CC_CHECK_CFLAGS_APPEND([-Wall -W -Wextra -pipe -Wno-long-long -Winline -Wvla -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wno-strict-aliasing -ffast-math -Wp,-D_FORTIFY_SOURCE=2 -fno-common -fdiagnostics-show-option -fno-omit-frame-pointer]) #### libtool stuff #### diff --git a/mutrace.c b/mutrace.c index ff65d90..9f81bc5 100644 --- a/mutrace.c +++ b/mutrace.c @@ -724,6 +724,36 @@ static bool verify_frame(const char *s) { return true; } +static int light_backtrace(void **buffer, int size) { +#if defined(__i386__) || defined(__x86_64__) + int osize = 0; + void *stackaddr; + size_t stacksize; + void *frame; + + pthread_attr_t attr; + pthread_getattr_np(pthread_self(), &attr); + pthread_attr_getstack(&attr, &stackaddr, &stacksize); + pthread_attr_destroy(&attr); + +#if defined(__i386__) + __asm__("mov %%ebp, %[frame]": [frame] "=r" (frame)); +#elif defined(__x86_64__) + __asm__("mov %%rbp, %[frame]": [frame] "=r" (frame)); +#endif + while (osize < size && + frame >= stackaddr && + frame < (void *)((char *)stackaddr + stacksize)) { + buffer[osize++] = *((void **)frame + 1); + frame = *(void **)frame; + } + + return osize; +#else + return real_backtrace(buffer, size); +#endif +} + static char* generate_stacktrace(void) { void **buffer; char **strings, *ret, *p; @@ -734,7 +764,7 @@ static char* generate_stacktrace(void) { buffer = malloc(sizeof(void*) * frames_max); assert(buffer); - n = real_backtrace(buffer, frames_max); + n = light_backtrace(buffer, frames_max); assert(n >= 0); strings = real_backtrace_symbols(buffer, n); -- cgit