diff options
author | Max Kellermann <max@musicpd.org> | 2017-02-01 21:16:50 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-02-01 21:36:58 +0100 |
commit | 05eac20ffe5af325ac7d4019e72d3ac0b69d494a (patch) | |
tree | 6f090bc757df52b49f632d02e1f082f9281f9e91 | |
parent | 38d263ac19013d6f5debbf2e6d0d74efd901977c (diff) |
lib/nfs/Connection: detect libnfs reconnect
When rpc_reconnect_requeue() gets called from inside nfs_service(),
the NfsInputStream can stall completely because the old socket has
been unregistered from epoll automatically, but the new one has never
been registered. Therefore, nfs_service() will never be called again.
This kludge attempts to detect this condition by checking
nfs_which_events()==POLLOUT.
https://bugs.musicpd.org/view.php?id=4081
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/lib/nfs/Connection.cxx | 13 |
2 files changed, 14 insertions, 1 deletions
@@ -1,4 +1,6 @@ ver 0.20.4 (not yet released) +* input + - nfs: fix freeze after reconnect * output - sndio: work around a libroar C++ incompatibility * workaround for GCC 4.9 "constexpr" bug diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index 16f6c001d..e41c4acd8 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -396,6 +396,17 @@ NfsConnection::ScheduleSocket() assert(GetEventLoop().IsInside()); assert(context != nullptr); + const int which_events = nfs_which_events(context); + + if (which_events == POLLOUT && SocketMonitor::IsDefined()) + /* kludge: if libnfs asks only for POLLOUT, it means + that it is currently waiting for the connect() to + finish - rpc_reconnect_requeue() may have been + called from inside nfs_service(); we must now + unregister the old socket and register the new one + instead */ + SocketMonitor::Steal(); + if (!SocketMonitor::IsDefined()) { int _fd = nfs_get_fd(context); if (_fd < 0) @@ -405,7 +416,7 @@ NfsConnection::ScheduleSocket() SocketMonitor::Open(_fd); } - SocketMonitor::Schedule(libnfs_to_events(nfs_which_events(context))); + SocketMonitor::Schedule(libnfs_to_events(which_events)); } inline int |