lib/nfs/Connection: implement mount timeout
This commit is contained in:
		
							
								
								
									
										1
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								NEWS
									
									
									
									
									
								
							@@ -3,6 +3,7 @@ ver 0.19.7 (not yet released)
 | 
				
			|||||||
  - nfs: fix crash while canceling a failing file open operation
 | 
					  - nfs: fix crash while canceling a failing file open operation
 | 
				
			||||||
  - nfs: fix memory leak on connection failure
 | 
					  - nfs: fix memory leak on connection failure
 | 
				
			||||||
  - nfs: fix reconnect after mount failure
 | 
					  - nfs: fix reconnect after mount failure
 | 
				
			||||||
 | 
					  - nfs: implement mount timeout (60 seconds)
 | 
				
			||||||
* playlist
 | 
					* playlist
 | 
				
			||||||
  - don't skip non-existent songs in "listplaylist"
 | 
					  - don't skip non-existent songs in "listplaylist"
 | 
				
			||||||
* fix memory allocator bug on Windows
 | 
					* fix memory allocator bug on Windows
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,8 @@ extern "C" {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <poll.h> /* for POLLIN, POLLOUT */
 | 
					#include <poll.h> /* for POLLIN, POLLOUT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static constexpr unsigned NFS_MOUNT_TIMEOUT = 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline bool
 | 
					inline bool
 | 
				
			||||||
NfsConnection::CancellableCallback::Stat(nfs_context *ctx,
 | 
					NfsConnection::CancellableCallback::Stat(nfs_context *ctx,
 | 
				
			||||||
					 const char *path,
 | 
										 const char *path,
 | 
				
			||||||
@@ -379,6 +381,11 @@ NfsConnection::DestroyContext()
 | 
				
			|||||||
	in_destroy = true;
 | 
						in_destroy = true;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mount_finished) {
 | 
				
			||||||
 | 
							assert(TimeoutMonitor::IsActive());
 | 
				
			||||||
 | 
							TimeoutMonitor::Cancel();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* cancel pending DeferredMonitor that was scheduled to notify
 | 
						/* cancel pending DeferredMonitor that was scheduled to notify
 | 
				
			||||||
	   new leases */
 | 
						   new leases */
 | 
				
			||||||
	DeferredMonitor::Cancel();
 | 
						DeferredMonitor::Cancel();
 | 
				
			||||||
@@ -528,6 +535,9 @@ NfsConnection::MountCallback(int status, gcc_unused nfs_context *nfs,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	mount_finished = true;
 | 
						mount_finished = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(TimeoutMonitor::IsActive() || in_destroy);
 | 
				
			||||||
 | 
						TimeoutMonitor::Cancel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (status < 0) {
 | 
						if (status < 0) {
 | 
				
			||||||
		postponed_mount_error.Format(nfs_domain, status,
 | 
							postponed_mount_error.Format(nfs_domain, status,
 | 
				
			||||||
					     "nfs_mount_async() failed: %s",
 | 
										     "nfs_mount_async() failed: %s",
 | 
				
			||||||
@@ -560,6 +570,8 @@ NfsConnection::MountInternal(Error &error)
 | 
				
			|||||||
	postponed_mount_error.Clear();
 | 
						postponed_mount_error.Clear();
 | 
				
			||||||
	mount_finished = false;
 | 
						mount_finished = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						TimeoutMonitor::ScheduleSeconds(NFS_MOUNT_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifndef NDEBUG
 | 
				
			||||||
	in_service = false;
 | 
						in_service = false;
 | 
				
			||||||
	in_event = false;
 | 
						in_event = false;
 | 
				
			||||||
@@ -620,6 +632,18 @@ NfsConnection::BroadcastError(Error &&error)
 | 
				
			|||||||
	BroadcastMountError(std::move(error));
 | 
						BroadcastMountError(std::move(error));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					NfsConnection::OnTimeout()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						assert(GetEventLoop().IsInside());
 | 
				
			||||||
 | 
						assert(!mount_finished);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mount_finished = true;
 | 
				
			||||||
 | 
						DestroyContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BroadcastMountError(Error(nfs_domain, "Mount timeout"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
NfsConnection::RunDeferred()
 | 
					NfsConnection::RunDeferred()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
#include "Lease.hxx"
 | 
					#include "Lease.hxx"
 | 
				
			||||||
#include "Cancellable.hxx"
 | 
					#include "Cancellable.hxx"
 | 
				
			||||||
#include "event/SocketMonitor.hxx"
 | 
					#include "event/SocketMonitor.hxx"
 | 
				
			||||||
 | 
					#include "event/TimeoutMonitor.hxx"
 | 
				
			||||||
#include "event/DeferredMonitor.hxx"
 | 
					#include "event/DeferredMonitor.hxx"
 | 
				
			||||||
#include "util/Error.hxx"
 | 
					#include "util/Error.hxx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,7 +41,7 @@ class NfsCallback;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * An asynchronous connection to a NFS server.
 | 
					 * An asynchronous connection to a NFS server.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class NfsConnection : SocketMonitor, DeferredMonitor {
 | 
					class NfsConnection : SocketMonitor, TimeoutMonitor, DeferredMonitor {
 | 
				
			||||||
	class CancellableCallback : public CancellablePointer<NfsCallback> {
 | 
						class CancellableCallback : public CancellablePointer<NfsCallback> {
 | 
				
			||||||
		NfsConnection &connection;
 | 
							NfsConnection &connection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -142,7 +143,8 @@ public:
 | 
				
			|||||||
	gcc_nonnull_all
 | 
						gcc_nonnull_all
 | 
				
			||||||
	NfsConnection(EventLoop &_loop,
 | 
						NfsConnection(EventLoop &_loop,
 | 
				
			||||||
		      const char *_server, const char *_export_name)
 | 
							      const char *_server, const char *_export_name)
 | 
				
			||||||
		:SocketMonitor(_loop), DeferredMonitor(_loop),
 | 
							:SocketMonitor(_loop), TimeoutMonitor(_loop),
 | 
				
			||||||
 | 
							 DeferredMonitor(_loop),
 | 
				
			||||||
		 server(_server), export_name(_export_name),
 | 
							 server(_server), export_name(_export_name),
 | 
				
			||||||
		 context(nullptr) {}
 | 
							 context(nullptr) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -227,6 +229,9 @@ private:
 | 
				
			|||||||
	/* virtual methods from SocketMonitor */
 | 
						/* virtual methods from SocketMonitor */
 | 
				
			||||||
	virtual bool OnSocketReady(unsigned flags) override;
 | 
						virtual bool OnSocketReady(unsigned flags) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* virtual methods from TimeoutMonitor */
 | 
				
			||||||
 | 
						void OnTimeout() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* virtual methods from DeferredMonitor */
 | 
						/* virtual methods from DeferredMonitor */
 | 
				
			||||||
	virtual void RunDeferred() override;
 | 
						virtual void RunDeferred() override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user