/* @@@HEAD@@@ // Coldmud signal handling. */ #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #include "config.h" #include "defs.h" #include "sig.h" #include "log.h" /* write_err() */ #include "execute.h" /* task() */ #include "cdc_string.h" /* string_from_chars() */ #include "data.h" #include "y.tab.h" void catch_SIGCHLD(int sig); void uninit_sig(void) { signal(SIGFPE, SIG_DFL); signal(SIGILL, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGALRM, SIG_DFL); signal(SIGUSR1, SIG_DFL); signal(SIGUSR2, SIG_DFL); signal(SIGCHLD, SIG_DFL); } void init_sig(void) { signal(SIGFPE, catch_signal); signal(SIGILL, catch_signal); signal(SIGQUIT, catch_signal); signal(SIGINT, catch_signal); signal(SIGHUP, catch_signal); signal(SIGTERM, catch_signal); signal(SIGALRM, catch_signal); signal(SIGUSR1, catch_signal); signal(SIGUSR2, catch_signal); signal(SIGCHLD, catch_SIGCHLD); } void catch_SIGCHLD(int sig) { waitpid(-1, NULL, WNOHANG); signal(SIGCHLD, catch_SIGCHLD); } char *sig_name(int sig) { switch(sig) { case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGQUIT: return "SIGQUIT"; case SIGSEGV: return "SIGSEGV"; case SIGINT: return "SIGINT"; case SIGHUP: return "SIGHUP"; case SIGTERM: return "SIGTERM"; case SIGALRM: return "SIGALRM"; case SIGUSR1: return "SIGUSR1"; case SIGUSR2: return "SIGUSR2"; default: return "Unknown"; } return NULL; } /* void catch_signal(int sig, int code, struct sigcontext *scp) { */ void catch_signal(int sig) { char *sptr; string_t *sigstr; data_t arg1, arg2; sptr = sig_name(sig); sigstr = string_from_chars(sptr, strlen(sptr)); write_err("Caught signal %d: %S", sig, sigstr); /* send a message to the system object */ arg1.type = SYMBOL; arg1.u.symbol = ident_get(sig_name(sig)); arg2.type = STRING; arg2.u.str = sigstr; task(NULL, SYSTEM_DBREF, signal_id, 2, &arg1, &arg2); /* figure out what to do */ switch(sig) { case SIGFPE: case SIGUSR1: case SIGUSR2: case SIGHUP: case SIGALRM: /* let the server do what it wants, don't shutdown */ break; case SIGILL: case SIGSEGV: /* lets panic and hopefully dump */ panic(sig_name(sig)); break; case SIGINT: case SIGQUIT: case SIGTERM: default: /* shutdown nicely */ if (running) { write_err("*** Attempting normal shutdown ***"); running = 0; } else { panic(sig_name(sig)); } break; } signal(sig, catch_signal); }