summaryrefslogtreecommitdiffstats
path: root/src/fuse
diff options
context:
space:
mode:
authorSimon Rettberg2015-12-17 16:33:22 +0100
committerSimon Rettberg2015-12-17 16:33:22 +0100
commitb47ba01818f2ea2ebd1cf1bf5e3e91e37c5f88dd (patch)
tree45665ec1c4f69c01438d92b6c5c85edd254ffbab /src/fuse
parent[SERVER] Performance: Optimized some functions (gprof) (diff)
downloaddnbd3-b47ba01818f2ea2ebd1cf1bf5e3e91e37c5f88dd.tar.gz
dnbd3-b47ba01818f2ea2ebd1cf1bf5e3e91e37c5f88dd.tar.xz
dnbd3-b47ba01818f2ea2ebd1cf1bf5e3e91e37c5f88dd.zip
[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.
Diffstat (limited to 'src/fuse')
-rw-r--r--src/fuse/connection.c3
-rw-r--r--src/fuse/main.c33
2 files changed, 35 insertions, 1 deletions
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 <inttypes.h>
#include <getopt.h>
#include <time.h>
+#include <signal.h>
#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;
}