diff --git a/configure.ac b/configure.ac index 70cd480e9f4..2b8d9b6457a 100644 --- a/configure.ac +++ b/configure.ac @@ -175,6 +175,13 @@ AC_ARG_ENABLE([all-asserts], ) AC_MSG_RESULT([$enable_all_asserts]) +AC_MSG_CHECKING([whether to enable event tracker]) +AC_ARG_ENABLE([event-tracker], + [AS_HELP_STRING([--enable-event-tracker],[turn on event tracker])], + [], + [enable_event_tracker=no] +) +AC_MSG_RESULT([$enable_event_tracker]) # Enable code coverage instrumentation only if requested by the user. AC_MSG_CHECKING([whether to code coverage]) @@ -973,10 +980,15 @@ fi if test "x${enable_mime_sanity_check}" = "xyes"; then TS_ADDTO(AM_CPPFLAGS, [-DENABLE_MIME_SANITY_CHECK]) fi + if test "x${enable_all_asserts}" = "xyes"; then TS_ADDTO(AM_CPPFLAGS, [-DENABLE_ALL_ASSERTS]) fi +if test "x${enable_event_tracker}" = "xyes"; then + TS_ADDTO(AM_CPPFLAGS, [-DENABLE_EVENT_TRACKER]) +fi + # Flags for ASAN if test "x${enable_asan}" = "xyes"; then if test "x${enable_tsan}" = "xyes" -o "x${enable_tsan}" = "xstatic"; then diff --git a/include/tscore/ink_stack_trace.h b/include/tscore/ink_stack_trace.h index 5d10fd03894..ff759b8b802 100644 --- a/include/tscore/ink_stack_trace.h +++ b/include/tscore/ink_stack_trace.h @@ -29,8 +29,15 @@ #ifdef __cplusplus extern "C" { #endif + /* dumps the current back trace to stderr */ void ink_stack_trace_dump(); + +/** + Get symbol of @n-th frame +*/ +const void *ink_backtrace(const int n); + #ifdef __cplusplus } #endif diff --git a/iocore/eventsystem/I_Event.h b/iocore/eventsystem/I_Event.h index 022f0adc7ec..10aad0ae518 100644 --- a/iocore/eventsystem/I_Event.h +++ b/iocore/eventsystem/I_Event.h @@ -200,6 +200,11 @@ class Event : public Action // inherited from Action::cancel // virtual void cancel(Continuation * c = nullptr); +#ifdef ENABLE_EVENT_TRACKER + void set_location(); + const void *get_location() const; +#endif + void free(); EThread *ethread = nullptr; @@ -239,6 +244,14 @@ class Event : public Action private: void *operator new(size_t size); // use the fast allocators +#ifdef ENABLE_EVENT_TRACKER + /** + Address of who scheduled this event + To get symbols, use backtrace_symbols(3) or external tools like `addr2line(1)` (Linux) or `atos(1)`(BSD). + */ + const void *_location = nullptr; +#endif + public: LINK(Event, link); diff --git a/iocore/eventsystem/P_UnixEThread.h b/iocore/eventsystem/P_UnixEThread.h index e4e8cb8e832..50d1885bcbc 100644 --- a/iocore/eventsystem/P_UnixEThread.h +++ b/iocore/eventsystem/P_UnixEThread.h @@ -32,6 +32,7 @@ #include "I_EThread.h" #include "I_EventProcessor.h" +#include const ink_hrtime DELAY_FOR_RETRY = HRTIME_MSECONDS(10); extern ink_thread_key ethread_key; @@ -39,7 +40,12 @@ extern ink_thread_key ethread_key; TS_INLINE Event * EThread::schedule_imm(Continuation *cont, int callback_event, void *cookie) { - Event *e = ::eventAllocator.alloc(); + Event *e = ::eventAllocator.alloc(); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, 0, 0)); @@ -48,7 +54,12 @@ EThread::schedule_imm(Continuation *cont, int callback_event, void *cookie) TS_INLINE Event * EThread::schedule_at(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = ::eventAllocator.alloc(); + Event *e = ::eventAllocator.alloc(); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, t, 0)); @@ -57,7 +68,12 @@ EThread::schedule_at(Continuation *cont, ink_hrtime t, int callback_event, void TS_INLINE Event * EThread::schedule_in(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = ::eventAllocator.alloc(); + Event *e = ::eventAllocator.alloc(); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, get_hrtime() + t, 0)); @@ -66,7 +82,12 @@ EThread::schedule_in(Continuation *cont, ink_hrtime t, int callback_event, void TS_INLINE Event * EThread::schedule_every(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = ::eventAllocator.alloc(); + Event *e = ::eventAllocator.alloc(); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; if (t < 0) { @@ -108,7 +129,12 @@ EThread::schedule(Event *e) TS_INLINE Event * EThread::schedule_imm_local(Continuation *cont, int callback_event, void *cookie) { - Event *e = EVENT_ALLOC(eventAllocator, this); + Event *e = EVENT_ALLOC(eventAllocator, this); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule_local(e->init(cont, 0, 0)); @@ -117,7 +143,12 @@ EThread::schedule_imm_local(Continuation *cont, int callback_event, void *cookie TS_INLINE Event * EThread::schedule_at_local(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = EVENT_ALLOC(eventAllocator, this); + Event *e = EVENT_ALLOC(eventAllocator, this); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule_local(e->init(cont, t, 0)); @@ -126,7 +157,12 @@ EThread::schedule_at_local(Continuation *cont, ink_hrtime t, int callback_event, TS_INLINE Event * EThread::schedule_in_local(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = EVENT_ALLOC(eventAllocator, this); + Event *e = EVENT_ALLOC(eventAllocator, this); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule_local(e->init(cont, get_hrtime() + t, 0)); @@ -135,7 +171,12 @@ EThread::schedule_in_local(Continuation *cont, ink_hrtime t, int callback_event, TS_INLINE Event * EThread::schedule_every_local(Continuation *cont, ink_hrtime t, int callback_event, void *cookie) { - Event *e = EVENT_ALLOC(eventAllocator, this); + Event *e = EVENT_ALLOC(eventAllocator, this); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; if (t < 0) { diff --git a/iocore/eventsystem/P_UnixEventProcessor.h b/iocore/eventsystem/P_UnixEventProcessor.h index a8ba4f475a1..9feec535b93 100644 --- a/iocore/eventsystem/P_UnixEventProcessor.h +++ b/iocore/eventsystem/P_UnixEventProcessor.h @@ -135,6 +135,11 @@ EventProcessor::schedule_imm(Continuation *cont, EventType et, int callback_even #ifdef ENABLE_TIME_TRACE e->start_time = Thread::get_hrtime(); #endif + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, 0, 0), et); @@ -147,6 +152,11 @@ EventProcessor::schedule_at(Continuation *cont, ink_hrtime t, EventType et, int ink_assert(t > 0); ink_assert(et < MAX_EVENT_TYPES); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, t, 0), et); @@ -158,6 +168,11 @@ EventProcessor::schedule_in(Continuation *cont, ink_hrtime t, EventType et, int Event *e = eventAllocator.alloc(); ink_assert(et < MAX_EVENT_TYPES); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; return schedule(e->init(cont, Thread::get_hrtime() + t, 0), et); @@ -170,6 +185,11 @@ EventProcessor::schedule_every(Continuation *cont, ink_hrtime t, EventType et, i ink_assert(t != 0); ink_assert(et < MAX_EVENT_TYPES); + +#ifdef ENABLE_EVENT_TRACKER + e->set_location(); +#endif + e->callback_event = callback_event; e->cookie = cookie; if (t < 0) { diff --git a/iocore/eventsystem/UnixEvent.cc b/iocore/eventsystem/UnixEvent.cc index b5589aedd10..983cf7a2632 100644 --- a/iocore/eventsystem/UnixEvent.cc +++ b/iocore/eventsystem/UnixEvent.cc @@ -29,6 +29,8 @@ *****************************************************************************/ #include "P_EventSystem.h" +#include "tscore/ink_stack_trace.h" + ClassAllocator eventAllocator("eventAllocator", 256); void @@ -104,3 +106,19 @@ Event::schedule_every(ink_hrtime aperiod, int acallback_event) ethread->EventQueueExternal.enqueue_local(this); } } + +#ifdef ENABLE_EVENT_TRACKER + +void +Event::set_location() +{ + _location = ink_backtrace(3); +} + +const void * +Event::get_location() const +{ + return _location; +} + +#endif diff --git a/src/tscore/ink_stack_trace.cc b/src/tscore/ink_stack_trace.cc index 568cc0dab7b..ace71496b6f 100644 --- a/src/tscore/ink_stack_trace.cc +++ b/src/tscore/ink_stack_trace.cc @@ -66,6 +66,25 @@ ink_stack_trace_dump() } } +const void * +ink_backtrace(const int n) +{ + if (INK_STACK_TRACE_MAX_LEVELS < n + 1) { + return nullptr; + } + + const int m = n + 1; + void *callstack[m]; + int frames = backtrace(callstack, m); + + const void *symbol = nullptr; + if (frames == m && callstack[n] != nullptr) { + symbol = callstack[n]; + } + + return symbol; +} + #else /* !TS_HAS_BACKTRACE */ void @@ -76,4 +95,10 @@ ink_stack_trace_dump() return; } +const void * +ink_backtrace(const int /* n */) +{ + return nullptr; +} + #endif /* TS_HAS_BACKTRACE */