aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnstein Ressem <aressem@verizonmedia.com>2020-04-02 15:13:44 +0200
committerGitHub <noreply@github.com>2020-04-02 15:13:44 +0200
commit7507e2bf9fb8f8aa384bc1aa0d5cbedd5ecb447b (patch)
tree7815c3ffe8d41ca8d974e63f644ec70e081e00b2
parenteb6b9add4b7d0c62d8e2a6d701b2854011910eee (diff)
parent9e8284c76aafa09b196563ae99d0d0a43d19414e (diff)
Merge pull request #12808 from vespa-engine/toregge/improve-signal-handler-shutdown-robustness
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;