summaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@online.no>2023-10-13 10:29:17 +0200
committerTor Egge <Tor.Egge@online.no>2023-10-13 10:29:17 +0200
commit718aa3afb05076ffcbc94af115384b26d6e7c4c6 (patch)
tree189ad5d675089588afa26c0192ebe89e7741fadb /config
parente7d54515ca2a5eceea0bf17c5b96b969aea8c53a (diff)
Avoid deadlock if GetConfigTask is running when closing FRTSource.
Diffstat (limited to 'config')
-rw-r--r--config/src/vespa/config/frt/frtsource.cpp26
-rw-r--r--config/src/vespa/config/frt/frtsource.h4
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