fuse_signals.c (2556B)
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 "qemu/osdep.h" 12#include "fuse_i.h" 13#include "fuse_lowlevel.h" 14 15 16static struct fuse_session *fuse_instance; 17 18static void exit_handler(int sig) 19{ 20 if (fuse_instance) { 21 fuse_session_exit(fuse_instance); 22 if (sig <= 0) { 23 fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n"); 24 abort(); 25 } 26 fuse_instance->error = sig; 27 } 28} 29 30static void do_nothing(int sig) 31{ 32 (void)sig; 33} 34 35static int set_one_signal_handler(int sig, void (*handler)(int), int remove) 36{ 37 struct sigaction sa; 38 struct sigaction old_sa; 39 40 memset(&sa, 0, sizeof(struct sigaction)); 41 sa.sa_handler = remove ? SIG_DFL : handler; 42 sigemptyset(&(sa.sa_mask)); 43 sa.sa_flags = 0; 44 45 if (sigaction(sig, NULL, &old_sa) == -1) { 46 fuse_log(FUSE_LOG_ERR, "fuse: cannot get old signal handler: %s\n", 47 strerror(errno)); 48 return -1; 49 } 50 51 if (old_sa.sa_handler == (remove ? handler : SIG_DFL) && 52 sigaction(sig, &sa, NULL) == -1) { 53 fuse_log(FUSE_LOG_ERR, "fuse: cannot set signal handler: %s\n", 54 strerror(errno)); 55 return -1; 56 } 57 return 0; 58} 59 60int fuse_set_signal_handlers(struct fuse_session *se) 61{ 62 /* 63 * If we used SIG_IGN instead of the do_nothing function, 64 * then we would be unable to tell if we set SIG_IGN (and 65 * thus should reset to SIG_DFL in fuse_remove_signal_handlers) 66 * or if it was already set to SIG_IGN (and should be left 67 * untouched. 68 */ 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 76 fuse_instance = se; 77 return 0; 78} 79 80void fuse_remove_signal_handlers(struct fuse_session *se) 81{ 82 if (fuse_instance != se) { 83 fuse_log(FUSE_LOG_ERR, 84 "fuse: fuse_remove_signal_handlers: unknown session\n"); 85 } else { 86 fuse_instance = NULL; 87 } 88 89 set_one_signal_handler(SIGHUP, exit_handler, 1); 90 set_one_signal_handler(SIGINT, exit_handler, 1); 91 set_one_signal_handler(SIGTERM, exit_handler, 1); 92 set_one_signal_handler(SIGPIPE, do_nothing, 1); 93}