From 46f9200cc9f48b503d278b2749db345a22d70449 Mon Sep 17 00:00:00 2001 From: Vasu Raman Date: Tue, 24 Nov 2020 21:28:38 -0800 Subject: [PATCH] Allow stacktrace across an eventer asynch --- src/eventer/eventer.h | 2 ++ src/eventer/eventer_impl.c | 7 +++++++ src/eventer/eventer_impl_private.h | 3 +++ src/utils/mtev_stacktrace.c | 26 +++++++++++++++++++++----- src/utils/mtev_stacktrace.h | 2 +- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/eventer/eventer.h b/src/eventer/eventer.h index e7e648648..0e1bdb188 100644 --- a/src/eventer/eventer.h +++ b/src/eventer/eventer.h @@ -49,6 +49,8 @@ extern "C" { #include #include +#define EVENTER_STACKTRACE_SIZE 128 + /* We use ETIMEDOUT, which might be ETIME on some platforms */ #ifndef ETIME #define ETIME ETIMEDOUT diff --git a/src/eventer/eventer_impl.c b/src/eventer/eventer_impl.c index f75082e13..07ba71e3d 100644 --- a/src/eventer/eventer_impl.c +++ b/src/eventer/eventer_impl.c @@ -1029,6 +1029,7 @@ int eventer_impl_init(void) { } void eventer_add_asynch_subqueue(eventer_jobq_t *q, eventer_t e, uint64_t subqueue) { + e->frames = mtev_backtrace_ucontext(e->callstack, NULL, EVENTER_STACKTRACE_SIZE, true); eventer_job_t *job; /* always use 0, if unspecified */ if(eventer_is_loop(e->thr_owner) < 0) e->thr_owner = eventer_impl_tls_data[0].tid; @@ -1059,6 +1060,7 @@ void eventer_add_asynch(eventer_jobq_t *q, eventer_t e) { } void eventer_add_asynch_dep_subqueue(eventer_jobq_t *q, eventer_t e, uint64_t subqueue) { + e->frames = mtev_backtrace_ucontext(e->callstack, NULL, EVENTER_STACKTRACE_SIZE, true); eventer_job_t *job; /* always use 0, if unspecified */ if(eventer_is_loop(e->thr_owner) < 0) e->thr_owner = eventer_impl_tls_data[0].tid; @@ -1089,6 +1091,7 @@ void eventer_add_asynch_dep(eventer_jobq_t *q, eventer_t e) { } mtev_boolean eventer_try_add_asynch_subqueue(eventer_jobq_t *q, eventer_t e, uint64_t subqueue) { + e->frames = mtev_backtrace_ucontext(e->callstack, NULL, EVENTER_STACKTRACE_SIZE, true); eventer_t timeout = NULL; eventer_job_t *job; /* always use 0, if unspecified */ @@ -1125,6 +1128,7 @@ mtev_boolean eventer_try_add_asynch(eventer_jobq_t *q, eventer_t e) { } mtev_boolean eventer_try_add_asynch_dep_subqueue(eventer_jobq_t *q, eventer_t e, uint64_t subqueue) { + e->frames = mtev_backtrace_ucontext(e->callstack, NULL, EVENTER_STACKTRACE_SIZE, true); eventer_t timeout = NULL; eventer_job_t *job; /* always use 0, if unspecified */ @@ -1464,6 +1468,7 @@ int eventer_run_callback(eventer_func_t f, eventer_t e, int m, void *c, struct t eventer_ref(e); eventer_set_this_event(e); eventer_callback_prep(e, m, c, n); + e->eventer_run_callback_end = &&end; rmask = f(e, m, c, n); eventer_callback_cleanup(e, rmask); mtev_boolean freed = eventer_deref(e); @@ -1485,6 +1490,8 @@ int eventer_run_callback(eventer_func_t f, eventer_t e, int m, void *c, struct t } } return rmask; +end: + ; } static void *eventer_thread_harness(void *ve) { diff --git a/src/eventer/eventer_impl_private.h b/src/eventer/eventer_impl_private.h index ace49365b..3922ccb36 100644 --- a/src/eventer/eventer_impl_private.h +++ b/src/eventer/eventer_impl_private.h @@ -77,6 +77,9 @@ struct name { \ pthread_t thr_owner; \ uint32_t refcnt; \ eventer_context_t ctx[MAX_EVENT_CTXS]; \ + int frames; \ + void *callstack[EVENTER_STACKTRACE_SIZE]; \ + void *eventer_run_callback_end; \ } EVENTER_STRUCT(_event); diff --git a/src/utils/mtev_stacktrace.c b/src/utils/mtev_stacktrace.c index f3b0e81bf..c2070fcc4 100644 --- a/src/utils/mtev_stacktrace.c +++ b/src/utils/mtev_stacktrace.c @@ -34,6 +34,7 @@ #include "mtev_sort.h" #include "mtev_skiplist.h" #include "mtev_hash.h" +#include "../eventer/eventer.h" #include #include #include @@ -969,7 +970,7 @@ mtev_stacktrace_internal(mtev_log_stream_t ls, void *caller, crash_in_crash = NULL; } -int mtev_backtrace_ucontext(void **callstack, ucontext_t *ctx, int cnt) { +int mtev_backtrace_ucontext(void **callstack, ucontext_t *ctx, int cnt, bool cross_eventer) { int frames = 0; #if defined(HAVE_LIBUNWIND) unw_cursor_t cursor; @@ -987,13 +988,28 @@ int mtev_backtrace_ucontext(void **callstack, ucontext_t *ctx, int cnt) { } unw_init_local(&cursor, (unw_context_t *)ctx); - int step_result = 1; + // this works but only allows us to go back through one asynch layer because we are pulling the + // event object for the current thread + eventer_t e = eventer_get_this_event(); + + // when backtracing from before eventer, remove the current function + int step_result = cross_eventer ? unw_step(&cursor) : 1; while (step_result > 0 && frames= (unw_word_t)eventer_run_callback && + pc <= (unw_word_t)e->eventer_run_callback_end) { + int eventer_frame = 0; + while(framesframes) { + callstack[frames++] = e->callstack[eventer_frame++]; + } + break; + } callstack[frames++] = (void *)pc; step_result = unw_step(&cursor); } @@ -1008,7 +1024,7 @@ void mtev_log_backtrace(mtev_log_stream_t ls, void **callstack, int cnt) { mtev_stacktrace_internal(ls, mtev_stacktrace, NULL, NULL, callstack, cnt); } int mtev_backtrace(void **callstack, int cnt) { - return mtev_backtrace_ucontext(callstack, NULL, cnt); + return mtev_backtrace_ucontext(callstack, NULL, cnt, false); } int global_in_stacktrace = 0; #if defined(__sun__) @@ -1016,7 +1032,7 @@ void mtev_stacktrace_ucontext(mtev_log_stream_t ls, ucontext_t *ucp) { if (ck_pr_fas_int(&global_in_stacktrace, 1)) return; void *callstack[128]; - int frames = mtev_backtrace_ucontext(callstack, ucp, 128); + int frames = mtev_backtrace_ucontext(callstack, ucp, 128, false); mtev_stacktrace_internal(ls, mtev_stacktrace, NULL, (void *)ucp, callstack, frames); global_in_stacktrace = 0; } @@ -1029,7 +1045,7 @@ void mtev_stacktrace_ucontext_skip(mtev_log_stream_t ls, ucontext_t *ucp, int ig struct sigaction sa, sasegv, saill, sabus; sigset_t smprev; void *callstack[128]; - int frames = mtev_backtrace_ucontext(callstack, ucp, 128); + int frames = mtev_backtrace_ucontext(callstack, ucp, 128, false); ignore = MIN(ignore, frames); memset(&sa, 0, sizeof(sa)); diff --git a/src/utils/mtev_stacktrace.h b/src/utils/mtev_stacktrace.h index 51310847a..d69db4415 100644 --- a/src/utils/mtev_stacktrace.h +++ b/src/utils/mtev_stacktrace.h @@ -68,7 +68,7 @@ API_EXPORT(int) mtev_backtrace(void **ips, int cnt); API_EXPORT(int) - mtev_backtrace_ucontext(void **ips, ucontext_t *ucp, int cnt); + mtev_backtrace_ucontext(void **ips, ucontext_t *ucp, int cnt, bool cross_eventer); API_EXPORT(int) mtev_aco_backtrace(aco_t *co, void **addrs, int addrs_len);