src/signal.c

Go to the documentation of this file.
00001 /*
00002  * signal.c
00003  *
00004  * $Id $
00005  */
00006 
00007 #include "config.h"
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <unistd.h>
00011 #include <sys/file.h>
00012 #include <sys/ioctl.h>
00013 #include <sys/wait.h>
00014 #include <signal.h>
00015 #include <errno.h>
00016 
00017 #include "debug.h"
00018 #include "mudconf.h"
00019 #include "externs.h"
00020 #include "flags.h"
00021 
00022 void signal_TERM(int, siginfo_t *, void *);
00023 void signal_PIPE(int, siginfo_t *, void *);
00024 void signal_USR1(int, siginfo_t *, void *);
00025 void signal_SEGV(int, siginfo_t *, void *);
00026 void signal_BUS(int, siginfo_t *, void *);
00027 
00028 struct sigaction saTERM = {.sa_handler = NULL,.sa_sigaction = signal_TERM,
00029         .sa_flags = SA_SIGINFO | SA_RESETHAND | SA_RESTART
00030 };
00031 
00032 struct sigaction saPIPE = {.sa_handler = NULL,.sa_sigaction = signal_PIPE,
00033         .sa_flags = SA_SIGINFO
00034 };
00035 
00036 struct sigaction saUSR1 = {.sa_handler = NULL,.sa_sigaction = signal_USR1,
00037         .sa_flags = SA_SIGINFO | SA_RESETHAND | SA_RESTART 
00038 };
00039 
00040 struct sigaction saSEGV = {.sa_handler = NULL,.sa_sigaction = signal_SEGV,
00041         .sa_flags = SA_SIGINFO | SA_RESETHAND | SA_RESTART
00042 };
00043 
00044 struct sigaction saBUS = {.sa_handler = NULL,.sa_sigaction = signal_BUS,
00045         .sa_flags = SA_SIGINFO | SA_RESETHAND | SA_RESTART
00046 };
00047 
00048 stack_t sighandler_stack;  
00049 stack_t regular_stack;
00050 
00051 #define ALT_STACK_SIZE (0x40000)
00052 #define ALT_STACK_ALIGN (0x1000)
00053 
00054 void bind_signals()
00055 {
00056     int error_code;
00057     dprintk("creating alternate signal stack.");
00058 #ifdef HAVE_POSIX_MEMALIGN
00059     error_code = posix_memalign(&sighandler_stack.ss_sp, ALT_STACK_ALIGN,
00060             ALT_STACK_SIZE);
00061 #else 
00062     sighandler_stack.ss_sp = malloc(ALT_STACK_SIZE);
00063     if(sighandler_stack.ss_sp != 0) error_code = 0;
00064 #endif
00065     if(error_code == 0) {
00066         sighandler_stack.ss_size = ALT_STACK_SIZE;
00067         sighandler_stack.ss_flags = 0;
00068         memset(sighandler_stack.ss_sp, 0, ALT_STACK_SIZE);
00069         dperror(sigaltstack(&sighandler_stack, &regular_stack) <0);
00070         dprintk("Current stack at 0x%x with length 0x%x and flags 0x%x", 
00071                 (unsigned int)regular_stack.ss_sp, regular_stack.ss_size, regular_stack.ss_flags);
00072         dprintk("Signal stack at 0x%x with length 0x%x and flags 0x%x", 
00073                 (unsigned int)sighandler_stack.ss_sp, sighandler_stack.ss_size, sighandler_stack.ss_flags);
00074         saSEGV.sa_flags |= SA_ONSTACK;
00075         saBUS.sa_flags |= SA_ONSTACK;
00076     } else {
00077         dprintk("posix_memalign failed with %s", strerror(error_code));
00078         log_error(LOG_PROBLEMS, "SIG", "ERR", 
00079                 "posix_memalign() failed with error %s, alternate stack not used.",
00080                 strerror(error_code));
00081         log_error(LOG_PROBLEMS, "SIG", "ERR", 
00082                 "running signal_handlers without sigaltstack() will corrupt your coredumps!");
00083         sighandler_stack.ss_sp = NULL;
00084     }
00085     dprintk("binding signals.");
00086     dperror(sigaction(SIGTERM, &saTERM, NULL) <0);
00087 //      sigaction(SIGPIPE, &saPIPE, NULL);
00088         sigaction(SIGUSR1, &saUSR1, NULL);
00089         sigaction(SIGSEGV, &saSEGV, NULL);
00090         sigaction(SIGBUS, &saBUS, NULL);
00091     signal(SIGCHLD, SIG_IGN);
00092     signal(SIGPIPE, SIG_IGN);
00093     dprintk("done.");
00094 }
00095 
00096 void unbind_signals()
00097 {
00098         signal(SIGTERM, SIG_DFL);
00099         signal(SIGPIPE, SIG_DFL);
00100         signal(SIGUSR1, SIG_DFL);
00101         signal(SIGSEGV, SIG_DFL);
00102         signal(SIGBUS, SIG_DFL);
00103     signal(SIGCHLD, SIG_DFL);
00104     if(sighandler_stack.ss_sp != NULL) {
00105         void *temp_ptr;
00106         sighandler_stack.ss_flags = SS_DISABLE;
00107         temp_ptr = sighandler_stack.ss_sp;
00108         sigaltstack(&sighandler_stack, NULL);
00109         free(temp_ptr);
00110         sighandler_stack.ss_sp = NULL;
00111     }
00112 }
00113 
00114 void signal_TERM(int signo, siginfo_t * siginfo, void *ucontext)
00115 {
00116         dprintk("caught SIGTERM");
00117         do_shutdown(NOTHING, 0, SHUTDN_EXIT, "received SIGTERM from kernel.");
00118 }
00119 
00120 void signal_PIPE(int signo, siginfo_t * siginfo, void *ucontext)
00121 {
00122     dprintk("caught SIGPIPE");
00123 #ifdef HAVE_SIGINFO_T_SI_FD
00124         eradicate_broken_fd(siginfo->si_fd);
00125 #else
00126         eradicate_broken_fd(-1);
00127 #endif
00128 }
00129 
00130 void signal_USR1(int signo, siginfo_t * siginfo, void *ucontext)
00131 {
00132     mux_release_socket();
00133     dprintk("caught SIGUSR1");
00134         do_restart(1, 1, 0);
00135 }
00136 
00137 void signal_SEGV(int signo, siginfo_t * siginfo, void *ucontext)
00138 {
00139     dprintk("caught SIGSEGV");
00140         int child;
00141     mux_release_socket();
00142         if(!(child = fork())) {
00143         sleep(1); // hag 20060404
00144                   // not sure if its necessary but I'm worried about
00145                   // a race.
00146         dprintk("(forked child) dumping restart database");
00147                 dump_restart_db();
00148         dprintk("(forked child) execing new copy of game.");
00149                 execl(mudstate.executable_path, mudstate.executable_path,
00150                           mudconf.config_file, NULL);
00151         } else {
00152                 switch (siginfo->si_code) {
00153                 case SEGV_MAPERR:
00154                         raw_broadcast(0,
00155                                                   "Game: Invalid access of unamapped memory at %p. Restarting from Checkpoint.",
00156                                                   siginfo->si_addr);
00157                         break;
00158                 case SEGV_ACCERR:
00159                         raw_broadcast(0,
00160                                                   "Game: Invalid access of protected memory at %p. Restarting from Checkpoint.",
00161                                                   siginfo->si_addr);
00162                         break;
00163                 default:
00164                         raw_broadcast(0,
00165                                                   "Game: Unhandled SEGV at %p. Restarting from checkpoint.",
00166                                                   siginfo->si_addr);
00167                         break;
00168                 }
00169                 dump_database_internal(DUMP_CRASHED);
00170                 report();
00171         }
00172 }
00173 
00174 void signal_BUS(int signo, siginfo_t * siginfo, void *ucontext)
00175 {
00176     dprintk("caught SIGBUS");
00177         int child;
00178     mux_release_socket();
00179         if(mudconf.sig_action != SA_EXIT && !(child = fork())) {
00180                 dump_restart_db();
00181                 execl(mudstate.executable_path, mudstate.executable_path,
00182                           mudconf.config_file, NULL);
00183         } else {
00184                 switch (siginfo->si_code) {
00185                 case BUS_ADRALN:
00186                         raw_broadcast(0,
00187                                                   "Game: Invalid address alignment accessing %p. Restarting from Checkpoint.",
00188                                                   siginfo->si_addr);
00189                         break;
00190                 case BUS_ADRERR:
00191                         raw_broadcast(0,
00192                                                   "Game: Invalid access of non-existent physical memory at %p. Restarting from Checkpoint.",
00193                                                   siginfo->si_addr);
00194                         break;
00195                 case BUS_OBJERR:
00196                         raw_broadcast(0,
00197                                                   "Game: Invalid object specific hardware error access at %p. Restarting from Checkpoint.",
00198                                                   siginfo->si_addr);
00199                         break;
00200                 default:
00201                         raw_broadcast(0,
00202                                                   "Game: Unhandled SEGV at %p. Restarting from checkpoint.",
00203                                                   siginfo->si_addr);
00204                         break;
00205                 }
00206                 dump_database_internal(DUMP_CRASHED);
00207                 report();
00208         }
00209 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7