diff options
author | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-11-03 01:56:51 +0300 |
---|---|---|
committer | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-11-03 02:17:18 +0300 |
commit | 1ff41fbc8d84eb71ae278c62500546cedab8dce2 (patch) | |
tree | 176c932f6ee293c097393f0f0a8c5a06ba60c637 /library/cpp/sighandler | |
parent | 47a733af080e57d9d3d7659b2458d9b21eaf7f18 (diff) | |
download | ydb-1ff41fbc8d84eb71ae278c62500546cedab8dce2.tar.gz |
YT-20376: TAsyncSignalsHandler improved thread safety
First commit
Diffstat (limited to 'library/cpp/sighandler')
-rw-r--r-- | library/cpp/sighandler/async_signals_handler.cpp | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/library/cpp/sighandler/async_signals_handler.cpp b/library/cpp/sighandler/async_signals_handler.cpp index 0c20dfccaa..ac3771f0d5 100644 --- a/library/cpp/sighandler/async_signals_handler.cpp +++ b/library/cpp/sighandler/async_signals_handler.cpp @@ -188,22 +188,33 @@ namespace { // It such situation we have 2 options: // - wait for auxiliary thread to die - which will cause dead lock // - destruct variable, ignoring thread - which will cause data corruption. - TAsyncSignalsHandler* SIGNALS_HANDLER = nullptr; + std::atomic<TAsyncSignalsHandler*> SIGNALS_HANDLER = nullptr; } void SetAsyncSignalHandler(int signum, THolder<TEventHandler> handler) { static TAdaptiveLock lock; - if (Y_UNLIKELY(SIGNALS_HANDLER == nullptr)) { + // Must be in HB with Handler's constructor. + auto* currentHandler = SIGNALS_HANDLER.load(std::memory_order::acquire); + + if (Y_UNLIKELY(currentHandler == nullptr)) { TGuard dnd(lock); - if (SIGNALS_HANDLER == nullptr) { + // If we read non-null here it means that we have a concurrent thread + // unlocking the lock establishing strongly HB with us. + // next line is sequenced before lock call thus relaxed is enough here. + currentHandler = SIGNALS_HANDLER.load(std::memory_order::relaxed); + + if (currentHandler == nullptr) { // NEVERS GETS DESTROYED - SIGNALS_HANDLER = new TAsyncSignalsHandler(); + currentHandler = new TAsyncSignalsHandler(); + + // Ensure HB with constructor for future readers. + SIGNALS_HANDLER.store(currentHandler, std::memory_order::release); } } - SIGNALS_HANDLER->Install(signum, std::move(handler)); + currentHandler->Install(signum, std::move(handler)); } #else //_win_ |