summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2017-02-01 21:16:50 +0100
committerMax Kellermann <max@musicpd.org>2017-02-01 21:36:58 +0100
commit05eac20ffe5af325ac7d4019e72d3ac0b69d494a (patch)
tree6f090bc757df52b49f632d02e1f082f9281f9e91
parent38d263ac19013d6f5debbf2e6d0d74efd901977c (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--NEWS2
-rw-r--r--src/lib/nfs/Connection.cxx13
2 files changed, 14 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 01c190ac9..d32a375c5 100644
--- a/NEWS
+++ b/NEWS
@@ -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