"Fossies" - the Fresh Open Source Software Archive

Member "shake-1.0/signals.c" (15 Nov 2014, 5295 Bytes) of package /linux/privat/shake-1.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "signals.c" see the Fossies "Dox" file reference documentation.

    1 /***************************************************************************/
    2 /*  Copyright (C) 2006-2011 Brice Arnould.                                 */
    3 /*                                                                         */
    4 /*  This file is part of ShaKe.                                            */
    5 /*                                                                         */
    6 /*  ShaKe is free software; you can redistribute it and/or modify          */
    7 /*  it under the terms of the GNU General Public License as published by   */
    8 /*  the Free Software Foundation; either version 3 of the License, or      */
    9 /*  (at your option) any later version.                                    */
   10 /*                                                                         */
   11 /*  This program is distributed in the hope that it will be useful,        */
   12 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
   13 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
   14 /*  GNU General Public License for more details.                           */
   15 /*                                                                         */
   16 /*  You should have received a copy of the GNU General Public License      */
   17 /*  along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   18 /***************************************************************************/
   19 
   20 #include "linux.h"      // OS_RESERVED_SIGNAL
   21 #include "signals.h"
   22 #include <assert.h>     // assert()
   23 #include <errno.h>      // errno
   24 #include <error.h>      // error()
   25 #include <signal.h>     // sigaction, sigprocmask, sigsetops
   26 #include <unistd.h>     // unlink()
   27 #include <stdbool.h>
   28 
   29 /* Those variables would have to be put in a thread-specific storage
   30  * for ShaKe to be multithread
   31  */
   32 static const char *current_msg = NULL;
   33 static const char *current_tempfile = NULL;
   34 static const char *current_file = NULL; // The file being shaked
   35 static volatile enum mode current_mode; // Tell in which mode we are, cf signals.h
   36 
   37 /*  If we're in CRITICAL mode, display current_msg and exit,
   38  * if we're in PREPARE mode, cancel the backup by going in cancel mode
   39  * else unlink the current_tempfile and call he default handler
   40  */
   41 static void
   42 handle_signals (int sig)
   43 {
   44   if (current_mode == CRITICAL)
   45     {
   46       /* Appart from SIGLOCKEXPIRED, we receive only SIGILL, SIGFPE or
   47        * SIGSEG in this mode (that is, fatal signals) */
   48       assert (current_msg);
   49       error (1, 0, "%s", current_msg);
   50     }
   51   else
   52     {
   53       assert (current_tempfile);
   54       unlink (current_tempfile);
   55       // Calls the default handler, because sa_flags == SA_RESETHAND
   56       raise (sig);
   57     }
   58 }
   59 
   60 /* Does what sigaction() would, except if the previous
   61  * handler is SIG_IGN in which case it does nothing.
   62  */
   63 static int
   64 sigaction_or_ignore (int signum, const struct sigaction *action,
   65              struct sigaction *old_action_res)
   66 {
   67   struct sigaction old_action;
   68   if (-1 == sigaction (signum, NULL, &old_action))
   69     return -1;
   70   else if (SIG_IGN == old_action.sa_handler)
   71     {
   72       /* Signal was set to "ignore", do not change it,
   73        * but set old_action_res if it is not NULL
   74        */
   75       if (NULL != old_action_res)
   76     *old_action_res = old_action;
   77       return 0;
   78     }
   79   else
   80     return sigaction (signum, action, old_action_res);
   81 }
   82 
   83 
   84 void
   85 install_sighandler (const char *tempfile)
   86 {
   87   assert (tempfile);
   88   struct sigaction sa;
   89   current_tempfile = tempfile;
   90   sigemptyset (&sa.sa_mask);
   91   // All signals after the firsts will be handled by system's default
   92   // handlers
   93   sa.sa_flags = SA_RESETHAND;
   94   // Automatically restart syscalls after handling a signal
   95   sa.sa_flags |= SA_RESTART;
   96   sa.sa_handler = handle_signals;
   97   /* Set our handler as the one that will handle critical situations */
   98   sigaction (SIGFPE, &sa, NULL);
   99   sigaction (SIGILL, &sa, NULL);
  100   sigaction (SIGPIPE, &sa, NULL);
  101   sigaction (SIGSEGV, &sa, NULL);
  102   sigaction (SIGTERM, &sa, NULL);
  103   sigaction (SIGUSR1, &sa, NULL);
  104   sigaction (SIGUSR2, &sa, NULL);
  105   sigaction (SIGBUS, &sa, NULL);
  106   sigaction (SIGXCPU, &sa, NULL);
  107   sigaction (SIGXFSZ, &sa, NULL);
  108   /* The same holds terminal-related signals, except that we need to
  109    * take in account the shell's dispositions.
  110    */
  111   sigaction_or_ignore (SIGHUP, &sa, NULL);
  112   sigaction_or_ignore (SIGINT, &sa, NULL);
  113   sigaction_or_ignore (SIGQUIT, &sa, NULL);
  114   sigaction_or_ignore (SIGTTIN, &sa, NULL);
  115   sigaction_or_ignore (SIGTTOU, &sa, NULL);
  116   /* Set the NORMAL mode */
  117   enter_normal_mode ();
  118 }
  119 
  120 void
  121 enter_normal_mode (void)
  122 {
  123   sigset_t sset;
  124   assert (NORMAL != current_mode);
  125   sigfillset (&sset);
  126   current_mode = NORMAL;
  127   current_msg = NULL;
  128   current_file = NULL;
  129   sigprocmask (SIG_UNBLOCK, &sset, NULL);
  130 }
  131 
  132 void
  133 enter_critical_mode (const char *msg)
  134 {
  135   sigset_t sset;
  136   assert (CRITICAL != current_mode);
  137   sigfillset (&sset);
  138   current_msg = msg;
  139   /* Don't suspend signals raised by internal errors */
  140   sigdelset (&sset, SIGILL);
  141   sigdelset (&sset, SIGFPE);
  142   sigdelset (&sset, SIGSEGV);
  143   /* Don't suspend signals reserved for use by the OS-specific layer */
  144   sigdelset (&sset, OS_RESERVED_SIGNAL);
  145   /* Stop and suspend works as usual */
  146   sigdelset (&sset, SIGTSTP);
  147   sigdelset (&sset, SIGSTOP);
  148   sigprocmask (SIG_BLOCK, &sset, NULL);
  149   current_mode = CRITICAL;
  150 }