From b47ba01818f2ea2ebd1cf1bf5e3e91e37c5f88dd Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 17 Dec 2015 16:33:22 +0100 Subject: [FUSE] Handle SIGINT/SIGTERM to abort pending reads Before, we would wait endlessly if there is a pending read request that doesn't get answered (e.g. because the server went down. That means you couldn't exit the client in that case. Now we use a signal handler to set a flag which causes the read to bail out and return EIO. --- src/fuse/connection.c | 3 +++ src/fuse/main.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'src/fuse') diff --git a/src/fuse/connection.c b/src/fuse/connection.c index 0a96055..170e329 100644 --- a/src/fuse/connection.c +++ b/src/fuse/connection.c @@ -215,6 +215,9 @@ bool connection_read(dnbd3_async_t *request) void connection_close() { + if ( keepRunning ) { + logadd( LOG_INFO, "Tearing down dnbd3 connections and workers" ); + } pthread_mutex_lock( &mutexInit ); keepRunning = false; if ( !connectionInitDone ) { diff --git a/src/fuse/main.c b/src/fuse/main.c index c2b07be..22c400e 100644 --- a/src/fuse/main.c +++ b/src/fuse/main.c @@ -26,6 +26,7 @@ #include #include #include +#include #define debugf(...) do { logadd( LOG_DEBUG1, __VA_ARGS__ ); } while (0) @@ -38,6 +39,9 @@ static bool useDebug = false; static log_info logInfo; static struct timespec startupTime; static uid_t owner; +static bool keepRunning = true; +static void (*fuse_sigIntHandler)(int) = NULL; +static void (*fuse_sigTermHandler)(int) = NULL; static int image_getattr(const char *path, struct stat *stbuf) @@ -138,7 +142,11 @@ static int image_read(const char *path, char *buf, size_t size, off_t offset, st return -EINVAL; } while ( !request.finished ) { - int ret = signal_wait( request.signalFd, 10000 ); + int ret = signal_wait( request.signalFd, 5000 ); + if ( !keepRunning ) { + connection_close(); + break; + } if ( ret < 0 ) { debugf( "fuse_read signal wait returned %d", ret ); } @@ -151,12 +159,35 @@ static int image_read(const char *path, char *buf, size_t size, off_t offset, st } } +static void image_sigHandler(int signum) { + keepRunning = false; + if ( signum == SIGINT && fuse_sigIntHandler != NULL ) { + fuse_sigIntHandler(signum); + } + if ( signum == SIGTERM && fuse_sigTermHandler != NULL ) { + fuse_sigTermHandler(signum); + } +} + static void* image_init(struct fuse_conn_info *conn UNUSED) { if ( !connection_initThreads() ) { logadd( LOG_ERROR, "Could not initialize threads for dnbd3 connection, exiting..." ); exit( EXIT_FAILURE ); } + // Prepare our handler + struct sigaction newHandler; + memset( &newHandler, 0, sizeof(newHandler) ); + newHandler.sa_handler = &image_sigHandler; + sigemptyset( &newHandler.sa_mask ); + struct sigaction oldHandler; + // Retrieve old handlers when setting + sigaction( SIGINT, &newHandler, &oldHandler ); + fuse_sigIntHandler = oldHandler.sa_handler; + logadd( LOG_DEBUG1, "Previous SIGINT handler was %p", fuse_sigIntHandler ); + sigaction( SIGTERM, &newHandler, &oldHandler ); + fuse_sigTermHandler = oldHandler.sa_handler; + logadd( LOG_DEBUG1, "Previous SIGTERM handler was %p", fuse_sigIntHandler ); return NULL; } -- cgit v1.2.3-55-g7522