summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLénaïc Huard <lenaic@lhuard.fr.eu.org>2010-02-17 21:35:18 +0100
committerLennart Poettering <lennart@poettering.net>2010-02-21 22:03:30 +0100
commitbedf81eb994a1cd88473e37babcdb336e6444ff8 (patch)
tree9f1da9b1e973588225c1fecd2356ff018987056b
parenta72470c0ed013fc90d2cb14a1a69594fa68d029e (diff)
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.
-rw-r--r--configure.ac2
-rw-r--r--mutrace.c32
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);