diff options
author | Max Kellermann <max@duempel.org> | 2014-11-25 10:42:52 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-11-25 13:31:18 +0100 |
commit | 3cef348f30ad8a018b1c46f257d3e719be3f96b0 (patch) | |
tree | 707c23f63f63838a5f7b4f895ae260a4e8bda48c /src/lib/nfs/Manager.cxx | |
parent | b293b160079fd19cfc675fa86c2b99695aac171f (diff) | |
download | mpd-3cef348f30ad8a018b1c46f257d3e719be3f96b0.tar.gz mpd-3cef348f30ad8a018b1c46f257d3e719be3f96b0.tar.xz mpd-3cef348f30ad8a018b1c46f257d3e719be3f96b0.zip |
lib/nfs/Manager: defer NfsConnection destruction
Avoids a crash that occurs when NfsConnection::OnSocketReady()
dereferences itself before returning.
Diffstat (limited to '')
-rw-r--r-- | src/lib/nfs/Manager.cxx | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx index c5aecf48d..6d50cce18 100644 --- a/src/lib/nfs/Manager.cxx +++ b/src/lib/nfs/Manager.cxx @@ -29,8 +29,10 @@ NfsManager::ManagedConnection::OnNfsConnectionError(Error &&error) { FormatError(error, "NFS error on %s:%s", GetServer(), GetExportName()); - manager.connections.erase(manager.connections.iterator_to(*this)); - delete this; + /* defer deletion so the caller + (i.e. NfsConnection::OnSocketReady()) can still use this + object */ + manager.ScheduleDelete(*this); } inline bool @@ -59,7 +61,9 @@ NfsManager::Compare::operator()(const ManagedConnection &a, NfsManager::~NfsManager() { - assert(loop.IsInside()); + assert(GetEventLoop().IsInside()); + + CollectGarbage(); connections.clear_and_dispose([](ManagedConnection *c){ delete c; @@ -71,13 +75,13 @@ NfsManager::GetConnection(const char *server, const char *export_name) { assert(server != nullptr); assert(export_name != nullptr); - assert(loop.IsInside()); + assert(GetEventLoop().IsInside()); Map::insert_commit_data hint; auto result = connections.insert_check(LookupKey{server, export_name}, Compare(), hint); if (result.second) { - auto c = new ManagedConnection(*this, loop, + auto c = new ManagedConnection(*this, GetEventLoop(), server, export_name); connections.insert_commit(*c, hint); return *c; @@ -85,3 +89,19 @@ NfsManager::GetConnection(const char *server, const char *export_name) return *result.first; } } + +void +NfsManager::CollectGarbage() +{ + assert(GetEventLoop().IsInside()); + + garbage.clear_and_dispose([](ManagedConnection *c){ + delete c; + }); +} + +void +NfsManager::OnIdle() +{ + CollectGarbage(); +} |