aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/nfs/Manager.hxx
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.hxx
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.hxx')
-rw-r--r--src/lib/nfs/Manager.hxx33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx
index 612b01f9c..130c81aca 100644
--- a/src/lib/nfs/Manager.hxx
+++ b/src/lib/nfs/Manager.hxx
@@ -23,14 +23,16 @@
#include "check.h"
#include "Connection.hxx"
#include "Compiler.h"
+#include "event/IdleMonitor.hxx"
#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/slist.hpp>
/**
* A manager for NFS connections. Handles multiple connections to
* multiple NFS servers.
*/
-class NfsManager {
+class NfsManager final : IdleMonitor {
struct LookupKey {
const char *server;
const char *export_name;
@@ -38,6 +40,7 @@ class NfsManager {
class ManagedConnection final
: public NfsConnection,
+ public boost::intrusive::slist_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>,
public boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
NfsManager &manager;
@@ -63,8 +66,6 @@ class NfsManager {
const LookupKey b) const;
};
- EventLoop &loop;
-
/**
* Maps server and export_name to #ManagedConnection.
*/
@@ -74,9 +75,18 @@ class NfsManager {
Map connections;
+ typedef boost::intrusive::slist<ManagedConnection> List;
+
+ /**
+ * A list of "garbage" connection objects. Their destruction
+ * is postponed because they were thrown into the garbage list
+ * when callers on the stack were still using them.
+ */
+ List garbage;
+
public:
NfsManager(EventLoop &_loop)
- :loop(_loop) {}
+ :IdleMonitor(_loop) {}
/**
* Must be run from EventLoop's thread.
@@ -86,6 +96,21 @@ public:
gcc_pure
NfsConnection &GetConnection(const char *server,
const char *export_name);
+
+private:
+ void ScheduleDelete(ManagedConnection &c) {
+ connections.erase(connections.iterator_to(c));
+ garbage.push_front(c);
+ IdleMonitor::Schedule();
+ }
+
+ /**
+ * Delete all connections on the #garbage list.
+ */
+ void CollectGarbage();
+
+ /* virtual methods from IdleMonitor */
+ void OnIdle() override;
};
#endif