Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 1 | /* |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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 | */ |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 10 | |
Dr. David Alan Gilbert | 09863eb | 2019-02-08 11:48:42 +0000 | [diff] [blame] | 11 | #include "qemu/osdep.h" |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 12 | #include "fuse_i.h" |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 13 | #include "fuse_lowlevel.h" |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 14 | |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 15 | |
| 16 | static struct fuse_session *fuse_instance; |
| 17 | |
| 18 | static void exit_handler(int sig) |
| 19 | { |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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 | } |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 28 | } |
| 29 | |
| 30 | static void do_nothing(int sig) |
| 31 | { |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 32 | (void)sig; |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | static int set_one_signal_handler(int sig, void (*handler)(int), int remove) |
| 36 | { |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 37 | struct sigaction sa; |
| 38 | struct sigaction old_sa; |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 39 | |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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; |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 44 | |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 45 | if (sigaction(sig, NULL, &old_sa) == -1) { |
Eryu Guan | fc1aed0 | 2019-08-09 16:25:36 +0800 | [diff] [blame] | 46 | fuse_log(FUSE_LOG_ERR, "fuse: cannot get old signal handler: %s\n", |
| 47 | strerror(errno)); |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 48 | return -1; |
| 49 | } |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 50 | |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 51 | if (old_sa.sa_handler == (remove ? handler : SIG_DFL) && |
| 52 | sigaction(sig, &sa, NULL) == -1) { |
Eryu Guan | fc1aed0 | 2019-08-09 16:25:36 +0800 | [diff] [blame] | 53 | fuse_log(FUSE_LOG_ERR, "fuse: cannot set signal handler: %s\n", |
| 54 | strerror(errno)); |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 55 | return -1; |
| 56 | } |
| 57 | return 0; |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | int fuse_set_signal_handlers(struct fuse_session *se) |
| 61 | { |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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 | } |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 75 | |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 76 | fuse_instance = se; |
| 77 | return 0; |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 78 | } |
| 79 | |
| 80 | void fuse_remove_signal_handlers(struct fuse_session *se) |
| 81 | { |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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 | } |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 88 | |
Dr. David Alan Gilbert | 7387863 | 2019-12-09 19:53:47 +0000 | [diff] [blame] | 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); |
Dr. David Alan Gilbert | ffcf8d9 | 2019-11-28 12:22:49 +0000 | [diff] [blame] | 93 | } |