qemu/tools/virtiofsd/fuse_signals.c
<<
>>
Prefs
   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}
  94