@@ -47,11 +47,22 @@ class RoutineInfo {
4747 }
4848};
4949
50+ static void thread_cleanup (void * arg) {
51+ int tid = *static_cast <int *>(arg);
52+ if (ProfiledThread::current () != nullptr ) {
53+ // In the process to tear down the thread, block any future signals.
54+ SignalBlocker blocker (false /* don't restore, block forever */ );
55+ }
56+ Profiler::unregisterThread (tid);
57+ ProfiledThread::release ();
58+ }
59+
5060// Wrapper around the real start routine.
5161// The wrapper:
5262// 1. Register the newly created thread to profiler
5363// 2. Call real start routine
5464// 3. Unregister the thread from profiler once the routine is completed.
65+ // Uses pthread_cleanup_push/pop so cleanup also runs if routine calls pthread_exit().
5566static void * start_routine_wrapper (void * args) {
5667 RoutineInfo* thr = (RoutineInfo*)args;
5768 func_start_routine routine = thr->routine ();
@@ -61,13 +72,9 @@ static void* start_routine_wrapper(void* args) {
6172 ProfiledThread::initCurrentThread ();
6273 int tid = ProfiledThread::currentTid ();
6374 Profiler::registerThread (tid);
75+ pthread_cleanup_push (thread_cleanup, &tid);
6476 void * result = routine (params);
65- if (ProfiledThread::current () != nullptr ) {
66- // In the process to tear down the thread, block any future signals.
67- SignalBlocker blocker (false /* don't restore, block forever */ );
68- }
69- Profiler::unregisterThread (tid);
70- ProfiledThread::release ();
77+ pthread_cleanup_pop (1 );
7178 return result;
7279}
7380
0 commit comments