From: Timo Sirainen Date: Sun, 26 Mar 2023 20:46:54 +0000 (+0300) Subject: lib: backtrace_get/append() - Add error_r parameter X-Git-Tag: 2.4.0~2840 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04d6a2e763bce8640a8192298025d0717e425a66;p=thirdparty%2Fdovecot%2Fcore.git lib: backtrace_get/append() - Add error_r parameter --- diff --git a/src/lib/backtrace-string.c b/src/lib/backtrace-string.c index b50827c381..6c458825a3 100644 --- a/src/lib/backtrace-string.c +++ b/src/lib/backtrace-string.c @@ -11,7 +11,7 @@ #include -static int backtrace_append_unwind(string_t *str) +static int backtrace_append_unwind(string_t *str, const char **error_r) { size_t str_orig_size = str_len(str); char proc_name[256]; @@ -23,11 +23,11 @@ static int backtrace_append_unwind(string_t *str) bool success = FALSE; if ((ret = unw_getcontext(&ctx)) != 0) { - str_printfa(str, "unw_getcontext() failed: %d", ret); + *error_r = t_strdup_printf("unw_getcontext() failed: %d", ret); return -1; } if ((ret = unw_init_local(&c, &ctx)) != 0) { - str_printfa(str, "unw_init_local() failed: %d", ret); + *error_r = t_strdup_printf("unw_init_local() failed: %d", ret); return -1; } @@ -55,7 +55,15 @@ static int backtrace_append_unwind(string_t *str) /* remove ' -> ' */ if (str->used > 4) str_truncate(str, str->used - 4); - return ret == 0 && success ? 0 : -1; + if (ret < 0) { + *error_r = t_strdup_printf("unw_step() failed: %d", ret); + return -1; + } + if (!success) { + *error_r = t_strdup_printf("No symbols found (process chrooted?)"); + return -1; + } + return 0; } #endif @@ -63,7 +71,7 @@ static int backtrace_append_unwind(string_t *str) /* Linux */ #include -static int backtrace_append_libc(string_t *str) +static int backtrace_append_libc(string_t *str, const char **error_r) { size_t str_orig_size = str_len(str); void *stack[MAX_STACK_SIZE]; @@ -71,10 +79,16 @@ static int backtrace_append_libc(string_t *str) int ret, i; ret = backtrace(stack, N_ELEMENTS(stack)); - if (ret <= 0) + if (ret <= 0) { + *error_r = "backtrace() failed"; return -1; + } strings = backtrace_symbols(stack, ret); + if (strings == NULL) { + *error_r = "backtrace_symbols() failed"; + return -1; + } for (i = 0; i < ret; i++) { if (str_len(str) > str_orig_size) str_append(str, " -> "); @@ -120,13 +134,15 @@ static int walk_callback(uintptr_t ptr, int signo ATTR_UNUSED, return 0; } -static int backtrace_append_libc(string_t *str) +static int backtrace_append_libc(string_t *str, const char **error_r) { ucontext_t uc; struct walk_context ctx; - if (getcontext(&uc) < 0) + if (getcontext(&uc) < 0) { + *error_r = t_strdup_printf("getcontext() failed: %m"); return -1; + } ctx.str = str; ctx.pos = 0; @@ -134,31 +150,33 @@ static int backtrace_append_libc(string_t *str) return 0; } #else -static int backtrace_append_libc(string_t *str ATTR_UNUSED) +static int +backtrace_append_libc(string_t *str ATTR_UNUSED, const char **error_r) { + *error_r = "Missing implementation"; return -1; } #endif -int backtrace_append(string_t *str) +int backtrace_append(string_t *str, const char **error_r) { #if defined(HAVE_LIBUNWIND) size_t orig_len = str_len(str); - if (backtrace_append_unwind(str) == 0) + if (backtrace_append_unwind(str, error_r) == 0) return 0; /* failed to get useful backtrace. libc's own method is likely better. */ str_truncate(str, orig_len); #endif - return backtrace_append_libc(str); + return backtrace_append_libc(str, error_r); } -int backtrace_get(const char **backtrace_r) +int backtrace_get(const char **backtrace_r, const char **error_r) { string_t *str; str = t_str_new(512); - if (backtrace_append(str) < 0) + if (backtrace_append(str, error_r) < 0) return -1; *backtrace_r = str_c(str); diff --git a/src/lib/backtrace-string.h b/src/lib/backtrace-string.h index ef448d8c2f..d9cbd9e2e9 100644 --- a/src/lib/backtrace-string.h +++ b/src/lib/backtrace-string.h @@ -2,7 +2,7 @@ #define BACKTRACE_STRING_H /* Returns 0 if ok, -1 if failure. */ -int backtrace_append(string_t *str); -int backtrace_get(const char **backtrace_r); +int backtrace_append(string_t *str, const char **error_r); +int backtrace_get(const char **backtrace_r, const char **error_r); #endif diff --git a/src/lib/data-stack.c b/src/lib/data-stack.c index acbedc977b..f7979bf28e 100644 --- a/src/lib/data-stack.c +++ b/src/lib/data-stack.c @@ -427,8 +427,8 @@ static void data_stack_send_grow_event(size_t last_alloc_size) /* Getting backtrace is potentially inefficient, so do it after checking if the event is wanted. Note that this prevents using the backtrace field in event field comparisons. */ - const char *backtrace; - if (backtrace_get(&backtrace) == 0) + const char *backtrace, *error; + if (backtrace_get(&backtrace, &error) == 0) event_add_str(event_datastack, "backtrace", backtrace); string_t *str = t_str_new(128); diff --git a/src/lib/failures.c b/src/lib/failures.c index 5990a750f5..007c5c930e 100644 --- a/src/lib/failures.c +++ b/src/lib/failures.c @@ -448,13 +448,13 @@ static int log_fd_write(int fd, const unsigned char *data, size_t len) static void ATTR_NORETURN default_fatal_finish(enum log_type type, int status) { - const char *backtrace; + const char *backtrace, *error; static int recursed = 0; recursed++; if ((type == LOG_TYPE_PANIC || status == FATAL_OUTOFMEM) && recursed == 1) { - if (backtrace_get(&backtrace) == 0) + if (backtrace_get(&backtrace, &error) == 0) i_error("Raw backtrace: %s", backtrace); } recursed--; diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c index 32fa9944ad..98c2dc2bf4 100644 --- a/src/lib/ioloop.c +++ b/src/lib/ioloop.c @@ -940,8 +940,8 @@ void io_loop_destroy(struct ioloop **_ioloop) } if (leaks) { - const char *backtrace; - if (backtrace_get(&backtrace) == 0) + const char *backtrace, *error; + if (backtrace_get(&backtrace, &error) == 0) i_warning("Raw backtrace for leaks: %s", backtrace); } diff --git a/src/lib/test-backtrace.c b/src/lib/test-backtrace.c index fdebe0fd38..dacb48d334 100644 --- a/src/lib/test-backtrace.c +++ b/src/lib/test-backtrace.c @@ -6,8 +6,9 @@ static void test_backtrace_append(void) { test_begin("backtrace_append"); string_t *bt = t_str_new(128); + const char *error; #if (defined(HAVE_LIBUNWIND)) - test_assert(backtrace_append(bt) == 0); + test_assert(backtrace_append(bt, &error) == 0); /* Check that there's a usable function in the backtrace. Note that this function may be inlined, so don't check for test_backtrace_get() */ @@ -16,12 +17,12 @@ static void test_backtrace_append(void) test_assert(strstr(str_c(bt), " backtrace_append") == NULL); #elif (defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)) || \ (defined(HAVE_WALKCONTEXT) && defined(HAVE_UCONTEXT_H)) - test_assert(backtrace_append(bt) == 0); + test_assert(backtrace_append(bt, &error) == 0); /* it should have some kind of main in it */ test_assert(strstr(str_c(bt), "main") != NULL); #else /* should not work in this context */ - test_assert(backtrace_append(bt) == -1); + test_assert(backtrace_append(bt, &error) == -1); #endif test_end(); } @@ -29,9 +30,9 @@ static void test_backtrace_append(void) static void test_backtrace_get(void) { test_begin("backtrace_get"); - const char *bt = NULL; + const char *bt = NULL, *error; #if (defined(HAVE_LIBUNWIND)) - test_assert(backtrace_get(&bt) == 0); + test_assert(backtrace_get(&bt, &error) == 0); /* Check that there's a usable function in the backtrace. Note that this function may be inlined, so don't check for test_backtrace_get() */ @@ -40,12 +41,12 @@ static void test_backtrace_get(void) test_assert(strstr(bt, " backtrace_get") == NULL); #elif (defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H)) || \ (defined(HAVE_WALKCONTEXT) && defined(HAVE_UCONTEXT_H)) - test_assert(backtrace_get(&bt) == 0); + test_assert(backtrace_get(&bt, &error) == 0); /* it should have some kind of main in it */ test_assert(strstr(bt, "main") != NULL); #else /* should not work in this context */ - test_assert(backtrace_get(&bt) == -1); + test_assert(backtrace_get(&bt, &error) == -1); #endif test_end(); }