diff options
author | Tor Egge <Tor.Egge@online.no> | 2023-10-13 10:29:17 +0200 |
---|---|---|
committer | Tor Egge <Tor.Egge@online.no> | 2023-10-13 10:29:17 +0200 |
commit | 718aa3afb05076ffcbc94af115384b26d6e7c4c6 (patch) | |
tree | 189ad5d675089588afa26c0192ebe89e7741fadb /config | |
parent | e7d54515ca2a5eceea0bf17c5b96b969aea8c53a (diff) |
Avoid deadlock if GetConfigTask is running when closing FRTSource.
Diffstat (limited to 'config')
-rw-r--r-- | config/src/vespa/config/frt/frtsource.cpp | 26 | ||||
-rw-r--r-- | config/src/vespa/config/frt/frtsource.h | 4 |
2 files changed, 22 insertions, 8 deletions
diff --git a/config/src/vespa/config/frt/frtsource.cpp b/config/src/vespa/config/frt/frtsource.cpp index 42472750114..b160984e0e8 100644 --- a/config/src/vespa/config/frt/frtsource.cpp +++ b/config/src/vespa/config/frt/frtsource.cpp @@ -39,7 +39,7 @@ FRTSource::FRTSource(std::shared_ptr<ConnectionFactory> connectionFactory, const _lock(), _inflight(), _task(std::make_unique<GetConfigTask>(_connectionFactory->getScheduler(), this)), - _closed(false) + _state(State::OPEN) { LOG(spam, "New source!"); } @@ -68,6 +68,9 @@ FRTSource::getConfig() FRT_RPCRequest * req = request->getRequest(); { std::lock_guard guard(_lock); + if (_state != State::OPEN) { + return; + } _inflight[req] = std::move(request); } connection->invoke(req, clientTimeout, this); @@ -126,11 +129,19 @@ FRTSource::close() { RequestMap inflight; { - std::lock_guard guard(_lock); - if (_closed) + std::unique_lock guard(_lock); + if (_state != State::OPEN) { + while (_state != State::CLOSED) { + _cond.wait(guard); // Wait for first close to finish + } return; - LOG(spam, "Killing task"); - _task->Kill(); + } + _state = State::CLOSING; + } + LOG(spam, "Killing task"); + _task->Kill(); + { + std::lock_guard guard(_lock); inflight = _inflight; } LOG(spam, "Aborting"); @@ -144,14 +155,17 @@ FRTSource::close() _cond.wait(guard); } LOG(spam, "closed"); + _state = State::CLOSED; + _cond.notify_all(); } void FRTSource::scheduleNextGetConfig() { std::lock_guard guard(_lock); - if (_closed) + if (_state != State::OPEN) { return; + } double sec = vespalib::to_s(_agent->getWaitTime()); LOG(debug, "Scheduling task in %f seconds", sec); _task->Schedule(sec); diff --git a/config/src/vespa/config/frt/frtsource.h b/config/src/vespa/config/frt/frtsource.h index 7488b4b57c8..92aa6a7370d 100644 --- a/config/src/vespa/config/frt/frtsource.h +++ b/config/src/vespa/config/frt/frtsource.h @@ -37,11 +37,11 @@ private: const FRTConfigRequestFactory & _requestFactory; std::unique_ptr<ConfigAgent> _agent; const ConfigKey _key; - std::mutex _lock; // Protects _inflight, _task and _closed + std::mutex _lock; // Protects _inflight, _task and _state std::condition_variable _cond; RequestMap _inflight; std::unique_ptr<FNET_Task> _task; - bool _closed; + enum class State : uint8_t { OPEN, CLOSING, CLOSED } _state; }; } // namespace config |