Skip to content

Commit b41ff44

Browse files
authored
Merge pull request #14 from ClickHouse/fix-deadlock
Fix deadlock with msan
2 parents 3e03c6d + be58af8 commit b41ff44

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

cpp/src/arrow/util/mutex.cc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,41 @@ struct AfterForkState {
6767
// The leak (only in child processes) is a small price to pay for robustness.
6868
Mutex* mutex = nullptr;
6969

70+
enum State {
71+
INITIALIZED,
72+
IN_PROCESS,
73+
NOT_INITIALIZED,
74+
};
75+
76+
std::atomic_int state = INITIALIZED;
77+
7078
private:
7179
AfterForkState() {
7280
pthread_atfork(/*prepare=*/nullptr, /*parent=*/nullptr, /*child=*/&AfterFork);
7381
}
7482

75-
static void AfterFork() { instance.mutex = new Mutex; }
83+
static void AfterFork() { instance.state.store(NOT_INITIALIZED); }
84+
7685
};
7786

7887
AfterForkState AfterForkState::instance;
7988
} // namespace
8089

81-
Mutex* GlobalForkSafeMutex() { return AfterForkState::instance.mutex; }
90+
Mutex* GlobalForkSafeMutex() {
91+
if (AfterForkState::instance.state.load() == AfterForkState::State::INITIALIZED) {
92+
return AfterForkState::instance.mutex;
93+
}
94+
95+
int expected = AfterForkState::State::NOT_INITIALIZED;
96+
if (AfterForkState::instance.state.compare_exchange_strong(expected, AfterForkState::State::IN_PROCESS)) {
97+
AfterForkState::instance.mutex = new Mutex;
98+
AfterForkState::instance.state.store(AfterForkState::State::INITIALIZED);
99+
} else {
100+
while (AfterForkState::instance.state.load() != AfterForkState::State::INITIALIZED);
101+
}
102+
103+
return AfterForkState::instance.mutex;
104+
}
82105
#endif // _WIN32
83106

84107
} // namespace util

0 commit comments

Comments
 (0)