1/* 2 FUSE: Filesystem in Userspace 3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 4 5 Utility functions for setting signal handlers. 6 7 This program can be distributed under the terms of the GNU LGPLv2. 8 See the file COPYING.LIB 9*/ 10 11#include "fuse_config.h" 12#include "fuse_lowlevel.h" 13#include "fuse_i.h" 14 15#include <stdio.h> 16#include <string.h> 17#include <signal.h> 18#include <stdlib.h> 19 20static struct fuse_session *fuse_instance; 21 22static void exit_handler(int sig) 23{ 24 if (fuse_instance) { 25 fuse_session_exit(fuse_instance); 26 if(sig <= 0) { 27 fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n"); 28 abort(); 29 } 30 fuse_instance->error = sig; 31 } 32} 33 34static void do_nothing(int sig) 35{ 36 (void) sig; 37} 38 39static int set_one_signal_handler(int sig, void (*handler)(int), int remove) 40{ 41 struct sigaction sa; 42 struct sigaction old_sa; 43 44 memset(&sa, 0, sizeof(struct sigaction)); 45 sa.sa_handler = remove ? SIG_DFL : handler; 46 sigemptyset(&(sa.sa_mask)); 47 sa.sa_flags = 0; 48 49 if (sigaction(sig, NULL, &old_sa) == -1) { 50 perror("fuse: cannot get old signal handler"); 51 return -1; 52 } 53 54 if (old_sa.sa_handler == (remove ? handler : SIG_DFL) && 55 sigaction(sig, &sa, NULL) == -1) { 56 perror("fuse: cannot set signal handler"); 57 return -1; 58 } 59 return 0; 60} 61 62int fuse_set_signal_handlers(struct fuse_session *se) 63{ 64 /* If we used SIG_IGN instead of the do_nothing function, 65 then we would be unable to tell if we set SIG_IGN (and 66 thus should reset to SIG_DFL in fuse_remove_signal_handlers) 67 or if it was already set to SIG_IGN (and should be left 68 untouched. */ 69 if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 || 70 set_one_signal_handler(SIGINT, exit_handler, 0) == -1 || 71 set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 || 72 set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1) 73 return -1; 74 75 fuse_instance = se; 76 return 0; 77} 78 79void fuse_remove_signal_handlers(struct fuse_session *se) 80{ 81 if (fuse_instance != se) 82 fuse_log(FUSE_LOG_ERR, 83 "fuse: fuse_remove_signal_handlers: unknown session\n"); 84 else 85 fuse_instance = NULL; 86 87 set_one_signal_handler(SIGHUP, exit_handler, 1); 88 set_one_signal_handler(SIGINT, exit_handler, 1); 89 set_one_signal_handler(SIGTERM, exit_handler, 1); 90 set_one_signal_handler(SIGPIPE, do_nothing, 1); 91} 92