Hi all,
There has been discussion on IRC about techniques for following requests
across events. I've slapped together a simple patch that attaches
backtraces to Continuations every time an event is scheduled. Since some
people may find this useful I wanted to "archive" it via the mailing list.
If it's very useful we can consider cleaning it up and adding it to master
via autoconf.

Brian


Example via gdb:
(gdb) p *((Continuation*)(contp)).bt@
((Continuation*)(contp))->current_bt_size
$10 = {0x4cc0f3 <EventProcessor::schedule(Event*, int, bool)+231>, 0x4cc279
<EventProcessor::schedule_imm(Continuation*, int, int, void*)+153>,
0x4f2209 <INKVConnInternal::reenable(VIO*)+97>, 0x50a893
<VIO::reenable()+63>, 0x5b6061 <HttpTunnel::producer_handler(int,
HttpTunnelProducer*)+1213>, 0x5b568e
<HttpTunnel::producer_run(HttpTunnelProducer*)+2732>, 0x5b4b1b
<HttpTunnel::tunnel_run(HttpTunnelProducer*)+155>, 0x57c46c
<HttpSM::set_next_state()+3450>, 0x57b6eb
<HttpSM::call_transact_and_set_next_state(void
(*)(HttpTransact::State*))+439>, 0x56883f
<HttpSM::handle_api_return()+313>, 0x568613 <HttpSM::state_api_callout(int,
void*)+2185>, 0x567d0f <HttpSM::state_api_callback(int, void*)+419>,
0x4fd83c <TSHttpTxnReenable(TSHttpTxn, TSEvent)+386>, 0x7ffff302814c
<(anonymous namespace)::handleGlobalPluginEvents(TSCont, TSEvent,
void*)+92>, 0x4f1a94 <INKContInternal::handle_event(int, void*)+176>,
0x4e8d82 <Continuation::handleEvent(int, void*)+108>, ...}



diff --git a/iocore/eventsystem/I_Continuation.h
b/iocore/eventsystem/I_Continuation.h
index 1de095b..cd8c297 100644
--- a/iocore/eventsystem/I_Continuation.h
+++ b/iocore/eventsystem/I_Continuation.h
@@ -56,6 +56,20 @@ class EThread;
 #define CONTINUATION_DONE            0
 #define CONTINUATION_CONT            1

+#ifndef CROSS_EVENT_STACK_TRACES
+#define CROSS_EVENT_STACK_TRACES
+#endif
+
+#ifdef CROSS_EVENT_STACK_TRACES
+#ifdef __GNUG__
+#define CROSS_EVENT_STACK_TRACES_ALWAYS_INLINE inline
__attribute__((always_inline))
+#else
+#define CROSS_EVENT_STACK_TRACES_ALWAYS_INLINE inline
+#endif
+#include <execinfo.h>
+#define BT_LIMIT_PER_EVENT 128
+#endif
+
 typedef int (Continuation::*ContinuationHandler) (int event, void *data);

 class force_VFPT_to_top
@@ -93,6 +107,27 @@ public:

 class Continuation: private force_VFPT_to_top
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+public:
+  size_t current_bt_size;
+  size_t max_bt_size;
+  void **bt;
+
+  void CROSS_EVENT_STACK_TRACES_ALWAYS_INLINE attach_current_stack_trace()
{
+    if (max_bt_size < (current_bt_size + BT_LIMIT_PER_EVENT)) {
+      // we need more space so we can attach at least BT_LIMIT_PER_EVENT
pointers
+      if (max_bt_size == 0) {
+        max_bt_size = BT_LIMIT_PER_EVENT;
+        bt = static_cast<void**>(ats_malloc(sizeof(void *) * max_bt_size));
+      } else {
+        max_bt_size <<= 1;
+        bt = static_cast<void **>(ats_realloc(bt, sizeof(void *) *
max_bt_size));
+      }
+    }
+    current_bt_size += backtrace (bt + current_bt_size,
BT_LIMIT_PER_EVENT);
+  }
+private:
+#endif
 public:

   /**
@@ -167,9 +202,14 @@ public:
 #define SET_HANDLER(_h) \
   (handler = ((ContinuationHandler)_h),handler_name = #_h)
 #else
+#ifdef CROSS_EVENT_STACK_TRACES
+#define SET_HANDLER(_h) \
+  (handler = ((ContinuationHandler)_h), current_bt_size = 0)
+#else
 #define SET_HANDLER(_h) \
   (handler = ((ContinuationHandler)_h))
 #endif
+#endif

 /**
   Sets a Continuation's handler.
@@ -184,13 +224,22 @@ public:
 #define SET_CONTINUATION_HANDLER(_c,_h) \
   (_c->handler = ((ContinuationHandler) _h),_c->handler_name = #_h)
 #else
+#ifdef CROSS_EVENT_STACK_TRACES
 #define SET_CONTINUATION_HANDLER(_c,_h) \
-  (_c->handler = ((ContinuationHandler) _h))
+  (_c->handler = ((ContinuationHandler) _h), _c->current_bt_size = 0);
+#else
+#define SET_CONTINUATION_HANDLER(_c,_h) \
+  (_c->handler = ((ContinuationHandler) _h));
+#endif
 #endif

 inline
 Continuation::Continuation(ProxyMutex * amutex)
-  : handler(NULL),
+  :
+#ifdef CROSS_EVENT_STACK_TRACES
+  current_bt_size(0), max_bt_size(0), bt(NULL),
+#endif
+handler(NULL),
 #ifdef DEBUG
     handler_name(NULL),
 #endif
diff --git a/iocore/eventsystem/P_UnixEThread.h
b/iocore/eventsystem/P_UnixEThread.h
index 462de69..1f2c4e7 100644
--- a/iocore/eventsystem/P_UnixEThread.h
+++ b/iocore/eventsystem/P_UnixEThread.h
@@ -91,6 +91,9 @@ EThread::schedule_every(Continuation * cont, ink_hrtime
t, int callback_event, v
 TS_INLINE Event *
 EThread::schedule(Event * e, bool fast_signal)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  e->continuation->attach_current_stack_trace();
+#endif
   e->ethread = this;
   ink_assert(tt == REGULAR);
   if (e->continuation->mutex)
@@ -141,6 +144,9 @@ EThread::schedule_every_local(Continuation * cont,
ink_hrtime t, int callback_ev
 TS_INLINE Event *
 EThread::schedule_local(Event * e)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  e->continuation->attach_current_stack_trace();
+#endif
   if (tt != REGULAR) {
     ink_assert(tt == DEDICATED);
     return eventProcessor.schedule(e, ET_CALL);
diff --git a/iocore/eventsystem/P_UnixEventProcessor.h
b/iocore/eventsystem/P_UnixEventProcessor.h
index d9a1e73..bae525e 100644
--- a/iocore/eventsystem/P_UnixEventProcessor.h
+++ b/iocore/eventsystem/P_UnixEventProcessor.h
@@ -74,6 +74,9 @@ EventProcessor::assign_thread(EventType etype)
 TS_INLINE Event *
 EventProcessor::schedule(Event * e, EventType etype, bool fast_signal)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  e->continuation->attach_current_stack_trace();
+#endif
   ink_assert(etype < MAX_EVENT_TYPES);
   e->ethread = assign_thread(etype);
   if (e->continuation->mutex)
diff --git a/iocore/eventsystem/UnixEvent.cc
b/iocore/eventsystem/UnixEvent.cc
index 634cee9..17ecfbf 100644
--- a/iocore/eventsystem/UnixEvent.cc
+++ b/iocore/eventsystem/UnixEvent.cc
@@ -34,6 +34,9 @@ ClassAllocator<Event> eventAllocator("eventAllocator",
256);
 void
 Event::schedule_imm(int acallback_event)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  continuation->attach_current_stack_trace();
+#endif
   callback_event = acallback_event;
   ink_assert(ethread == this_ethread());
   if (in_the_priority_queue)
@@ -49,6 +52,9 @@ Event::schedule_imm(int acallback_event)
 void
 Event::schedule_at(ink_hrtime atimeout_at, int acallback_event)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  continuation->attach_current_stack_trace();
+#endif
   callback_event = acallback_event;
   ink_assert(ethread == this_ethread());
   ink_assert(atimeout_at > 0);
@@ -65,6 +71,9 @@ Event::schedule_at(ink_hrtime atimeout_at, int
acallback_event)
 void
 Event::schedule_in(ink_hrtime atimeout_in, int acallback_event)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  continuation->attach_current_stack_trace();
+#endif
   callback_event = acallback_event;
   ink_assert(ethread == this_ethread());
   if (in_the_priority_queue)
@@ -80,6 +89,9 @@ Event::schedule_in(ink_hrtime atimeout_in, int
acallback_event)
 void
 Event::schedule_every(ink_hrtime aperiod, int acallback_event)
 {
+#ifdef CROSS_EVENT_STACK_TRACES
+  continuation->attach_current_stack_trace();
+#endif
   callback_event = acallback_event;
   ink_assert(ethread == this_ethread());
   ink_assert(aperiod != 0);

Reply via email to