summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-09-15 23:54:23 +0200
committerLennart Poettering <lennart@poettering.net>2009-09-15 23:54:23 +0200
commitb4be616900ff4a10c6f37c66a4d1e9862d88db6f (patch)
tree7504381fd1d96567d765b6eac1cc0b8685c886ce
parentf951e6c0654349b3a58e88f55f1b0930c6096236 (diff)
redirect backtrace() so that we don't enter an endless loop if the user calls backtrace() himself
-rw-r--r--mutrace.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/mutrace.c b/mutrace.c
index a5c521a..fb0b435 100644
--- a/mutrace.c
+++ b/mutrace.c
@@ -103,6 +103,9 @@ static int (*real_pthread_create)(pthread_t *newthread, const pthread_attr_t *at
static void (*real_exit)(int status) __attribute__((noreturn)) = NULL;
static void (*real__exit)(int status) __attribute__((noreturn)) = NULL;
static void (*real__Exit)(int status) __attribute__((noreturn)) = NULL;
+static int (*real_backtrace)(void **array, int size) = NULL;
+static char **(*real_backtrace_symbols)(void *const *array, int size) = NULL;
+static void (*real_backtrace_symbols_fd)(void *const *array, int size, int fd) = NULL;
static struct mutex_info **alive_mutexes = NULL, **dead_mutexes = NULL;
static pthread_mutex_t *mutexes_lock = NULL;
@@ -211,6 +214,10 @@ static void load_functions(void) {
LOAD_FUNC(_exit);
LOAD_FUNC(_Exit);
+ LOAD_FUNC(backtrace);
+ LOAD_FUNC(backtrace_symbols);
+ LOAD_FUNC(backtrace_symbols_fd);
+
loaded = true;
recursive = false;
}
@@ -587,10 +594,10 @@ static char* generate_stacktrace(void) {
buffer = malloc(sizeof(void*) * frames_max);
assert(buffer);
- n = backtrace(buffer, frames_max);
+ n = real_backtrace(buffer, frames_max);
assert(n >= 0);
- strings = backtrace_symbols(buffer, n);
+ strings = real_backtrace_symbols(buffer, n);
assert(strings);
free(buffer);
@@ -967,3 +974,39 @@ int pthread_create(pthread_t *newthread,
return real_pthread_create(newthread, attr, start_routine, arg);
}
+
+int backtrace(void **array, int size) {
+ int r;
+
+ load_functions();
+
+ /* backtrace() internally uses a mutex. To avoid an endless
+ * loop we need to disable ourselves so that we don't try to
+ * call backtrace() ourselves when looking at that lock. */
+
+ recursive = true;
+ r = real_backtrace(array, size);
+ recursive = false;
+
+ return r;
+}
+
+char **backtrace_symbols(void *const *array, int size) {
+ char **r;
+
+ load_functions();
+
+ recursive = true;
+ r = real_backtrace_symbols(array, size);
+ recursive = false;
+
+ return r;
+}
+
+void backtrace_symbols_fd(void *const *array, int size, int fd) {
+ load_functions();
+
+ recursive = true;
+ real_backtrace_symbols_fd(array, size, fd);
+ recursive = false;
+}