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