aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/nfs/Manager.cxx
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-11-25 10:42:52 +0100
committerMax Kellermann <max@duempel.org>2014-11-25 13:31:18 +0100
commit3cef348f30ad8a018b1c46f257d3e719be3f96b0 (patch)
tree707c23f63f63838a5f7b4f895ae260a4e8bda48c /src/lib/nfs/Manager.cxx
parentb293b160079fd19cfc675fa86c2b99695aac171f (diff)
downloadmpd-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 'src/lib/nfs/Manager.cxx')
-rw-r--r--src/lib/nfs/Manager.cxx30
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();
+}