aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@verizonmedia.com>2020-04-02 14:08:49 +0200
committerTor Egge <Tor.Egge@verizonmedia.com>2020-04-02 14:08:49 +0200
commit9e8284c76aafa09b196563ae99d0d0a43d19414e (patch)
treeaa1b2d1817e594037e5abb2917bea4f7f5d72a91
parent448f5a09f05e0d17d58f9433d8fe78403f0ff78d (diff)
Improve SignalHandler::shutdown robustness.
-rw-r--r--vespalib/src/vespa/vespalib/util/signalhandler.cpp19
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;