xref: /third_party/libfuse/lib/fuse_signals.c (revision 6881f68f)
16881f68fSopenharmony_ci/*
26881f68fSopenharmony_ci  FUSE: Filesystem in Userspace
36881f68fSopenharmony_ci  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
46881f68fSopenharmony_ci
56881f68fSopenharmony_ci  Utility functions for setting signal handlers.
66881f68fSopenharmony_ci
76881f68fSopenharmony_ci  This program can be distributed under the terms of the GNU LGPLv2.
86881f68fSopenharmony_ci  See the file COPYING.LIB
96881f68fSopenharmony_ci*/
106881f68fSopenharmony_ci
116881f68fSopenharmony_ci#include "fuse_config.h"
126881f68fSopenharmony_ci#include "fuse_lowlevel.h"
136881f68fSopenharmony_ci#include "fuse_i.h"
146881f68fSopenharmony_ci
156881f68fSopenharmony_ci#include <stdio.h>
166881f68fSopenharmony_ci#include <string.h>
176881f68fSopenharmony_ci#include <signal.h>
186881f68fSopenharmony_ci#include <stdlib.h>
196881f68fSopenharmony_ci
206881f68fSopenharmony_cistatic struct fuse_session *fuse_instance;
216881f68fSopenharmony_ci
226881f68fSopenharmony_cistatic void exit_handler(int sig)
236881f68fSopenharmony_ci{
246881f68fSopenharmony_ci	if (fuse_instance) {
256881f68fSopenharmony_ci		fuse_session_exit(fuse_instance);
266881f68fSopenharmony_ci		if(sig <= 0) {
276881f68fSopenharmony_ci			fuse_log(FUSE_LOG_ERR, "assertion error: signal value <= 0\n");
286881f68fSopenharmony_ci			abort();
296881f68fSopenharmony_ci		}
306881f68fSopenharmony_ci		fuse_instance->error = sig;
316881f68fSopenharmony_ci	}
326881f68fSopenharmony_ci}
336881f68fSopenharmony_ci
346881f68fSopenharmony_cistatic void do_nothing(int sig)
356881f68fSopenharmony_ci{
366881f68fSopenharmony_ci	(void) sig;
376881f68fSopenharmony_ci}
386881f68fSopenharmony_ci
396881f68fSopenharmony_cistatic int set_one_signal_handler(int sig, void (*handler)(int), int remove)
406881f68fSopenharmony_ci{
416881f68fSopenharmony_ci	struct sigaction sa;
426881f68fSopenharmony_ci	struct sigaction old_sa;
436881f68fSopenharmony_ci
446881f68fSopenharmony_ci	memset(&sa, 0, sizeof(struct sigaction));
456881f68fSopenharmony_ci	sa.sa_handler = remove ? SIG_DFL : handler;
466881f68fSopenharmony_ci	sigemptyset(&(sa.sa_mask));
476881f68fSopenharmony_ci	sa.sa_flags = 0;
486881f68fSopenharmony_ci
496881f68fSopenharmony_ci	if (sigaction(sig, NULL, &old_sa) == -1) {
506881f68fSopenharmony_ci		perror("fuse: cannot get old signal handler");
516881f68fSopenharmony_ci		return -1;
526881f68fSopenharmony_ci	}
536881f68fSopenharmony_ci
546881f68fSopenharmony_ci	if (old_sa.sa_handler == (remove ? handler : SIG_DFL) &&
556881f68fSopenharmony_ci	    sigaction(sig, &sa, NULL) == -1) {
566881f68fSopenharmony_ci		perror("fuse: cannot set signal handler");
576881f68fSopenharmony_ci		return -1;
586881f68fSopenharmony_ci	}
596881f68fSopenharmony_ci	return 0;
606881f68fSopenharmony_ci}
616881f68fSopenharmony_ci
626881f68fSopenharmony_ciint fuse_set_signal_handlers(struct fuse_session *se)
636881f68fSopenharmony_ci{
646881f68fSopenharmony_ci	/* If we used SIG_IGN instead of the do_nothing function,
656881f68fSopenharmony_ci	   then we would be unable to tell if we set SIG_IGN (and
666881f68fSopenharmony_ci	   thus should reset to SIG_DFL in fuse_remove_signal_handlers)
676881f68fSopenharmony_ci	   or if it was already set to SIG_IGN (and should be left
686881f68fSopenharmony_ci	   untouched. */
696881f68fSopenharmony_ci	if (set_one_signal_handler(SIGHUP, exit_handler, 0) == -1 ||
706881f68fSopenharmony_ci	    set_one_signal_handler(SIGINT, exit_handler, 0) == -1 ||
716881f68fSopenharmony_ci	    set_one_signal_handler(SIGTERM, exit_handler, 0) == -1 ||
726881f68fSopenharmony_ci	    set_one_signal_handler(SIGPIPE, do_nothing, 0) == -1)
736881f68fSopenharmony_ci		return -1;
746881f68fSopenharmony_ci
756881f68fSopenharmony_ci	fuse_instance = se;
766881f68fSopenharmony_ci	return 0;
776881f68fSopenharmony_ci}
786881f68fSopenharmony_ci
796881f68fSopenharmony_civoid fuse_remove_signal_handlers(struct fuse_session *se)
806881f68fSopenharmony_ci{
816881f68fSopenharmony_ci	if (fuse_instance != se)
826881f68fSopenharmony_ci		fuse_log(FUSE_LOG_ERR,
836881f68fSopenharmony_ci			"fuse: fuse_remove_signal_handlers: unknown session\n");
846881f68fSopenharmony_ci	else
856881f68fSopenharmony_ci		fuse_instance = NULL;
866881f68fSopenharmony_ci
876881f68fSopenharmony_ci	set_one_signal_handler(SIGHUP, exit_handler, 1);
886881f68fSopenharmony_ci	set_one_signal_handler(SIGINT, exit_handler, 1);
896881f68fSopenharmony_ci	set_one_signal_handler(SIGTERM, exit_handler, 1);
906881f68fSopenharmony_ci	set_one_signal_handler(SIGPIPE, do_nothing, 1);
916881f68fSopenharmony_ci}
92