diff options
author | Max Kellermann <max@musicpd.org> | 2017-02-01 22:05:33 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-02-01 22:05:33 +0100 |
commit | df4af2b5501f332db248aedd792c2b55789823c5 (patch) | |
tree | e53a63614964da8dd8ddb699e68854ccd95a91f3 /src/lib/nfs | |
parent | 97132e3d385ae84f7aaeb6c94f24d2cf41d39b9c (diff) | |
parent | 0a033fb10aeca8bf6e6bfc9a2f9d9e793ee61ac9 (diff) |
Merge tag 'v0.20.4'
release v0.20.4
Diffstat (limited to 'src/lib/nfs')
-rw-r--r-- | src/lib/nfs/Connection.cxx | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index 16f6c001d..b417f2fab 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,8 @@ NfsConnection::ScheduleSocket() SocketMonitor::Open(_fd); } - SocketMonitor::Schedule(libnfs_to_events(nfs_which_events(context))); + SocketMonitor::Schedule(libnfs_to_events(which_events) + | SocketMonitor::HANGUP); } inline int @@ -442,10 +454,14 @@ NfsConnection::OnSocketReady(unsigned flags) bool closed = false; const bool was_mounted = mount_finished; - if (!mount_finished) + if (!mount_finished || (flags & SocketMonitor::HANGUP) != 0) /* until the mount is finished, the NFS client may use various sockets, therefore we unregister and re-register it each time */ + /* also re-register the socket if we got a HANGUP, + which is a sure sign that libnfs will close the + socket, which can lead to a race condition if + epoll_ctl() is called later */ SocketMonitor::Steal(); const int result = Service(flags); |