File tree Expand file tree Collapse file tree 1 file changed +25
-2
lines changed
Expand file tree Collapse file tree 1 file changed +25
-2
lines changed Original file line number Diff line number Diff 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
7887AfterForkState 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
You can’t perform that action at this time.
0 commit comments