Skip to content

Commit 405fea2

Browse files
Find potential deadlocks using tryLock in profiler shutdown
1 parent 3a493be commit 405fea2

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

src/mutex.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Mutex::Mutex() {
1313
pthread_mutex_init(&_mutex, &attr);
1414
}
1515

16+
bool Mutex::tryLock() {
17+
return pthread_mutex_trylock(&_mutex) == 0;
18+
}
19+
1620
void Mutex::lock() {
1721
pthread_mutex_lock(&_mutex);
1822
}

src/mutex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Mutex {
1717
public:
1818
Mutex();
1919

20+
bool tryLock();
2021
void lock();
2122
void unlock();
2223
};

src/profiler.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static Instrument instrument;
6868

6969
static ProfilingWindow profiling_window;
7070

71+
static volatile bool _in_jfrsync = false;
7172

7273
struct MethodSample {
7374
u64 samples;
@@ -1211,7 +1212,9 @@ Error Profiler::start(Arguments& args, bool reset) {
12111212
switchLibraryTrap(true);
12121213

12131214
if (args._output == OUTPUT_JFR) {
1215+
_in_jfrsync = args._jfr_sync != NULL;
12141216
error = _jfr.start(args, reset);
1217+
_in_jfrsync = false;
12151218
if (error) {
12161219
uninstallTraps();
12171220
switchLibraryTrap(false);
@@ -2024,6 +2027,21 @@ Error Profiler::restart(Arguments& args) {
20242027
}
20252028

20262029
void Profiler::shutdown(Arguments& args) {
2030+
// Potential deadlock may happen between current thread & profiling thread due to usage of jfrsync
2031+
// To avoid that we use `tryLock` rather than `lock`
2032+
if (!_state_lock.tryLock()) {
2033+
volatile bool sleep = true;
2034+
for (int i = 0; i < 10 && !_state_lock.tryLock(); i++) {
2035+
OS::uninterruptibleSleep(10000000, &sleep); // 10ms
2036+
}
2037+
}
2038+
2039+
// deadlock detected, skip stopping the profiler.
2040+
if (!_state_lock.tryLock() && _in_jfrsync) {
2041+
Log::warn("%s", "async-profiler deadlock detected during process shutdown, skipping the shutdown hooks");
2042+
return;
2043+
}
2044+
20272045
MutexLocker ml(_state_lock);
20282046

20292047
// The last chance to dump profile before VM terminates

0 commit comments

Comments
 (0)