diff options
author | Tor Egge <Tor.Egge@verizonmedia.com> | 2020-04-02 14:08:49 +0200 |
---|---|---|
committer | Tor Egge <Tor.Egge@verizonmedia.com> | 2020-04-02 14:08:49 +0200 |
commit | 9e8284c76aafa09b196563ae99d0d0a43d19414e (patch) | |
tree | aa1b2d1817e594037e5abb2917bea4f7f5d72a91 | |
parent | 448f5a09f05e0d17d58f9433d8fe78403f0ff78d (diff) |
Improve SignalHandler::shutdown robustness.
-rw-r--r-- | vespalib/src/vespa/vespalib/util/signalhandler.cpp | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/vespalib/src/vespa/vespalib/util/signalhandler.cpp b/vespalib/src/vespa/vespalib/util/signalhandler.cpp index 0a5eea0d327..c4fb7cfa517 100644 --- a/vespalib/src/vespa/vespalib/util/signalhandler.cpp +++ b/vespalib/src/vespa/vespalib/util/signalhandler.cpp @@ -2,6 +2,11 @@ #include "signalhandler.h" #include <cassert> +#include <atomic> +#include <chrono> +#include <thread> + +using namespace std::chrono_literals; namespace vespalib { @@ -9,6 +14,9 @@ std::vector<SignalHandler*> SignalHandler::_handlers; namespace { +// 31 bit concurrency counter, 1 (lsb) bit indicating shutdown +std::atomic<int> signal_counter; + class Shutdown { public: @@ -39,9 +47,13 @@ Shutdown shutdown; void SignalHandler::handleSignal(int signal) { - if ((((size_t)signal) < _handlers.size()) && (_handlers[signal] != 0)) { - _handlers[signal]->gotSignal(); + static_assert(std::atomic<int>::is_always_lock_free, "signal_counter must be lock free"); + if ((signal_counter.fetch_add(2) & 1) == 0) { + if ((((size_t)signal) < _handlers.size()) && (_handlers[signal] != 0)) { + _handlers[signal]->gotSignal(); + } } + signal_counter.fetch_sub(2); } void @@ -108,6 +120,9 @@ SignalHandler::unhook() void SignalHandler::shutdown() { + while ((signal_counter.fetch_or(1) & ~1) != 0) { + std::this_thread::sleep_for(10ms); + } for (std::vector<SignalHandler*>::iterator it = _handlers.begin(), ite = _handlers.end(); it != ite; |