Skip to content

Commit 28e23ee

Browse files
committed
Adjust ThreadEnd hook
If the TLS cleanup fires before the JVMTI hook, we want to ensure that we don't crash while retrieving the ProfiledThread - Add a check on validity of ProfiledThread
1 parent 90651f5 commit 28e23ee

2 files changed

Lines changed: 25 additions & 11 deletions

File tree

ddprof-lib/src/main/cpp/profiler.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,32 @@ void Profiler::onThreadStart(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread) {
119119

120120
void Profiler::onThreadEnd(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread) {
121121
ProfiledThread *current = ProfiledThread::current();
122-
int slot_id = current->filterSlotId();
123-
int tid = current->tid();
124-
if (_thread_filter.enabled()) {
125-
_thread_filter.unregisterThread(slot_id);
126-
current->setFilterSlotId(-1);
122+
int tid = -1;
123+
124+
if (current != nullptr) {
125+
// ProfiledThread is alive - do full cleanup and use efficient tid access
126+
int slot_id = current->filterSlotId();
127+
tid = current->tid();
128+
129+
if (_thread_filter.enabled()) {
130+
_thread_filter.unregisterThread(slot_id);
131+
current->setFilterSlotId(-1);
132+
}
133+
134+
ProfiledThread::release();
135+
} else {
136+
// ProfiledThread already cleaned up - try to get tid from JVMTI as fallback
137+
tid = VMThread::nativeThreadId(jni, thread);
138+
if (tid < 0) {
139+
// No ProfiledThread AND can't get tid from JVMTI - nothing we can do
140+
return;
141+
}
127142
}
128-
updateThreadName(jvmti, jni, thread, true);
129-
143+
144+
// These should always run if we have a valid tid
145+
updateThreadName(jvmti, jni, thread, false); // false = not self
130146
_cpu_engine->unregisterThread(tid);
131-
// unregister here because JNI callers generally don't know about thread exits
132147
_wall_engine->unregisterThread(tid);
133-
ProfiledThread::release();
134148
}
135149

136150
int Profiler::registerThread(int tid) {

ddprof-lib/src/main/cpp/threadFilter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ThreadFilter {
1717
static constexpr int kChunkMask = kChunkSize - 1;
1818
static constexpr int kMaxThreads = 2048;
1919
static constexpr int kMaxChunks = (kMaxThreads + kChunkSize - 1) / kChunkSize; // = 8 chunks
20-
// High-performance free list using Treiber stack, 64 shards
20+
// High-performance free list using Treiber stack, 64 shards
2121
static constexpr int kFreeListSize = 1024;
2222
static constexpr int kShardCount = 64; // power-of-two
2323
ThreadFilter();
@@ -64,7 +64,7 @@ class ThreadFilter {
6464
std::unique_ptr<FreeListNode[]> _free_list;
6565

6666
struct alignas(64) ShardHead { std::atomic<int> head{-1}; };
67-
static ShardHead _free_heads[kShardCount]; // one cache-line each
67+
static ShardHead _free_heads[kShardCount]; // one cache-line each
6868

6969
static inline int shardOf(int tid) { return tid & (kShardCount - 1); }
7070
static inline int shardOfSlot(int s){ return s & (kShardCount - 1); }

0 commit comments

Comments
 (0)