diff --git a/src/event/MultiSocketMonitor.cxx b/src/event/MultiSocketMonitor.cxx index 9a28dd71d..02a51e96f 100644 --- a/src/event/MultiSocketMonitor.cxx +++ b/src/event/MultiSocketMonitor.cxx @@ -31,9 +31,15 @@ MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop) :IdleMonitor(_loop), TimeoutMonitor(_loop) { } -MultiSocketMonitor::~MultiSocketMonitor() +void +MultiSocketMonitor::Reset() { - // TODO + assert(GetEventLoop().IsInsideOrNull()); + + fds.clear(); + IdleMonitor::Cancel(); + TimeoutMonitor::Cancel(); + ready = refresh = false; } void diff --git a/src/event/MultiSocketMonitor.hxx b/src/event/MultiSocketMonitor.hxx index d6c400b9e..db6bec3cb 100644 --- a/src/event/MultiSocketMonitor.hxx +++ b/src/event/MultiSocketMonitor.hxx @@ -119,11 +119,26 @@ public: static constexpr unsigned HANGUP = SocketMonitor::HANGUP; MultiSocketMonitor(EventLoop &_loop); - ~MultiSocketMonitor(); using IdleMonitor::GetEventLoop; -public: + /** + * Clear the socket list and disable all #EventLoop + * registrations. Run this in the #EventLoop thread before + * destroying this object. + * + * Later, this object can be reused and reactivated by calling + * InvalidateSockets(). + * + * Note that this class doesn't have a destructor which calls + * this method, because this would be racy and thus pointless: + * at the time ~MultiSocketMonitor() is called, our virtual + * methods have been morphed to be pure again, and in the + * meantime the #EventLoop thread could invoke those pure + * methods. + */ + void Reset(); + /** * Invalidate the socket list. A call to PrepareSockets() is * scheduled which will then update the list. diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index 7c5e55e56..40967dd40 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -98,12 +98,8 @@ public: } ~AlsaInputStream() { - /* ClearSocketList must be called from within the - IOThread; if we don't do it manually here, the - ~MultiSocketMonitor() will do it in the current - thread */ BlockingCall(MultiSocketMonitor::GetEventLoop(), [this](){ - ClearSocketList(); + MultiSocketMonitor::Reset(); }); snd_pcm_close(capture_handle);