Unverified Commit dfa342e8 authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #881

Fix potential deadlock in proxy_registry
parents 6eeee3f3 10f5de50
...@@ -88,34 +88,57 @@ bool proxy_registry::empty() const { ...@@ -88,34 +88,57 @@ bool proxy_registry::empty() const {
void proxy_registry::erase(const node_id& nid) { void proxy_registry::erase(const node_id& nid) {
CAF_LOG_TRACE(CAF_ARG(nid)); CAF_LOG_TRACE(CAF_ARG(nid));
std::unique_lock<std::mutex> guard{mtx_}; // Move submap for `nid` to a local variable.
auto i = proxies_.find(nid); proxy_map tmp;
if (i == proxies_.end()) {
return; using std::swap;
for (auto& kvp : i->second) std::unique_lock<std::mutex> guard{mtx_};
auto i = proxies_.find(nid);
if (i == proxies_.end())
return;
swap(i->second, tmp);
proxies_.erase(i);
}
// Call kill_proxy outside the critical section.
for (auto& kvp : tmp)
kill_proxy(kvp.second, exit_reason::remote_link_unreachable); kill_proxy(kvp.second, exit_reason::remote_link_unreachable);
proxies_.erase(i);
} }
void proxy_registry::erase(const node_id& nid, actor_id aid, error rsn) { void proxy_registry::erase(const node_id& nid, actor_id aid, error rsn) {
CAF_LOG_TRACE(CAF_ARG(nid) << CAF_ARG(aid)); CAF_LOG_TRACE(CAF_ARG(nid) << CAF_ARG(aid));
std::unique_lock<std::mutex> guard{mtx_}; // Try to find the actor handle in question.
auto i = proxies_.find(nid); strong_actor_ptr erased_proxy;
if (i != proxies_.end()) { {
auto& submap = i->second; using std::swap;
auto j = submap.find(aid); std::unique_lock<std::mutex> guard{mtx_};
if (j == submap.end()) auto i = proxies_.find(nid);
return; if (i != proxies_.end()) {
kill_proxy(j->second, std::move(rsn)); auto& submap = i->second;
submap.erase(j); auto j = submap.find(aid);
if (submap.empty()) if (j == submap.end())
proxies_.erase(i); return;
swap(j->second, erased_proxy);
submap.erase(j);
if (submap.empty())
proxies_.erase(i);
}
} }
// Call kill_proxy outside the critical section.
if (erased_proxy != nullptr)
kill_proxy(erased_proxy, std::move(rsn));
} }
void proxy_registry::clear() { void proxy_registry::clear() {
std::unique_lock<std::mutex> guard{mtx_}; CAF_LOG_TRACE("");
for (auto& kvp : proxies_) // Move the content of proxies_ to a local variable.
std::unordered_map<node_id, proxy_map> tmp;
{
using std::swap;
std::unique_lock<std::mutex> guard{mtx_};
swap(proxies_, tmp);
}
// Call kill_proxy outside the critical section.
for (auto& kvp : tmp)
for (auto& sub_kvp : kvp.second) for (auto& sub_kvp : kvp.second)
kill_proxy(sub_kvp.second, exit_reason::remote_link_unreachable); kill_proxy(sub_kvp.second, exit_reason::remote_link_unreachable);
proxies_.clear(); proxies_.clear();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment