Move signal handling to server.c

Improve diagnostic messages from signal handler

For some reason, signal handler was not being set in server process when called
from main()
This commit is contained in:
Andrew Bettison 2012-05-09 19:06:44 +09:30
parent f1e23d463b
commit d96d8ff8d6
3 changed files with 168 additions and 188 deletions

191
dna.c
View File

@ -248,11 +248,6 @@ int usage(char *complaint)
}
#ifndef DNA_NO_MAIN
char *exec_args[128];
int exec_argc=0;
int servalShutdown=0;
const char *thisinstancepath=NULL;
const char *serval_instancepath()
{
@ -288,170 +283,6 @@ int create_serval_instance_dir() {
return 0;
}
void signal_handler( int signal ) {
switch (signal) {
case SIGQUIT:
serverCleanUp();
exit(0);
case SIGHUP:
case SIGINT:
/* Terminate the server process. The shutting down should be done from the main-line code
rather than here, so we first try to tell the mainline code to do so. If, however, this is
not the first time we have been asked to shut down, then we will do it here. */
server_shutdown_check();
WHY("Asking Serval process to shutdown cleanly");
servalShutdown = 1;
return;
}
/* oops - caught a bad signal -- exec() ourselves fresh */
char signalName[64];
snprintf(signalName,63,"signal %d",signal); signalName[63]=0;
switch(signal) {
#ifdef SIGHUP
case SIGHUP: snprintf(signalName,63,"SIG %s (%d)","hangup",signal);
break;
#endif
#ifdef SIGINT
case SIGINT: snprintf(signalName,63,"SIG %s (%d)","interrupt",signal);
break;
#endif
#ifdef SIGQUIT
case SIGQUIT: snprintf(signalName,63,"SIG %s (%d)","quit",signal);
break;
#endif
#ifdef SIGILL
case SIGILL: snprintf(signalName,63,"SIG %s (%d)","illegal instruction (not reset when caught)",signal);
break;
#endif
#ifdef SIGTRAP
case SIGTRAP: snprintf(signalName,63,"SIG %s (%d)","trace trap (not reset when caught)",signal);
break;
#endif
#ifdef SIGABRT
case SIGABRT: snprintf(signalName,63,"SIG %s (%d)","abort()",signal);
break;
#endif
#ifdef SIGPOLL
case SIGPOLL: snprintf(signalName,63,"SIG %s (%d)","pollable event ([XSR] generated, not supported)",signal);
break;
#endif
#ifdef SIGEMT
case SIGEMT: snprintf(signalName,63,"SIG %s (%d)","EMT instruction",signal);
break;
#endif
#ifdef SIGFPE
case SIGFPE: snprintf(signalName,63,"SIG %s (%d)","floating point exception",signal);
break;
#endif
#ifdef SIGKILL
case SIGKILL: snprintf(signalName,63,"SIG %s (%d)","kill (cannot be caught or ignored)",signal);
break;
#endif
#ifdef SIGBUS
case SIGBUS: snprintf(signalName,63,"SIG %s (%d)","bus error",signal);
break;
#endif
#ifdef SIGSEGV
case SIGSEGV: snprintf(signalName,63,"SIG %s (%d)","segmentation violation",signal);
break;
#endif
#ifdef SIGSYS
case SIGSYS: snprintf(signalName,63,"SIG %s (%d)","bad argument to system call",signal);
break;
#endif
#ifdef SIGPIPE
case SIGPIPE: snprintf(signalName,63,"SIG %s (%d)","write on a pipe with no one to read it",signal);
break;
#endif
#ifdef SIGALRM
case SIGALRM: snprintf(signalName,63,"SIG %s (%d)","alarm clock",signal);
break;
#endif
#ifdef SIGTERM
case SIGTERM: snprintf(signalName,63,"SIG %s (%d)","software termination signal from kill",signal);
break;
#endif
#ifdef SIGURG
case SIGURG: snprintf(signalName,63,"SIG %s (%d)","urgent condition on IO channel",signal);
break;
#endif
#ifdef SIGSTOP
case SIGSTOP: snprintf(signalName,63,"SIG %s (%d)","sendable stop signal not from tty",signal);
break;
#endif
#ifdef SIGTSTP
case SIGTSTP: snprintf(signalName,63,"SIG %s (%d)","stop signal from tty",signal);
break;
#endif
#ifdef SIGCONT
case SIGCONT: snprintf(signalName,63,"SIG %s (%d)","continue a stopped process",signal);
break;
#endif
#ifdef SIGCHLD
case SIGCHLD: snprintf(signalName,63,"SIG %s (%d)","to parent on child stop or exit",signal);
break;
#endif
#ifdef SIGTTIN
case SIGTTIN: snprintf(signalName,63,"SIG %s (%d)","to readers pgrp upon background tty read",signal);
break;
#endif
#ifdef SIGTTOU
case SIGTTOU: snprintf(signalName,63,"SIG %s (%d)","like TTIN for output if (tp->t_local&LTOSTOP)",signal);
break;
#endif
#ifdef SIGIO
#if SIGIO != SIGPOLL
case SIGIO: snprintf(signalName,63,"SIG %s (%d)","input/output possible signal",signal);
break;
#endif
#endif
#ifdef SIGXCPU
case SIGXCPU: snprintf(signalName,63,"SIG %s (%d)","exceeded CPU time limit",signal);
break;
#endif
#ifdef SIGXFSZ
case SIGXFSZ: snprintf(signalName,63,"SIG %s (%d)","exceeded file size limit",signal);
break;
#endif
#ifdef SIGVTALRM
case SIGVTALRM: snprintf(signalName,63,"SIG %s (%d)","virtual time alarm",signal);
break;
#endif
#ifdef SIGPROF
case SIGPROF: snprintf(signalName,63,"SIG %s (%d)","profiling time alarm",signal);
break;
#endif
#ifdef SIGWINCH
case SIGWINCH: snprintf(signalName,63,"SIG %s (%d)","window size changes",signal);
break;
#endif
#ifdef SIGINFO
case SIGINFO: snprintf(signalName,63,"SIG %s (%d)","information request",signal);
break;
#endif
#ifdef SIGUSR1
case SIGUSR1: snprintf(signalName,63,"SIG %s (%d)","user defined signal 1",signal);
break;
#endif
#ifdef SIGUSR2
case SIGUSR2: snprintf(signalName,63,"SIG %s (%d)","user defined signal 2",signal);
break;
#endif
}
signalName[63]=0;
fprintf(stderr,"Caught terminal signal %s -- respawning.\n",signalName);
if (sock>-1) close(sock);
int i;
for(i=0;i<overlay_interface_count;i++)
if (overlay_interfaces[i].fd>-1)
close(overlay_interfaces[i].fd);
execv(exec_args[0],exec_args);
/* Quit if the exec() fails */
exit(-3);
}
int setVerbosity(const char *optarg) {
long long old_debug=debug;
debug=strtoll(optarg,NULL,10);
@ -499,32 +330,16 @@ int main(int argc, char **argv)
int instance=-1;
int foregroundMode=0;
memabuseInit();
#if defined WIN32
WSADATA wsa_data;
WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
/* Catch sigsegv and other crash signals so that we can relaunch ourselves */
for(exec_argc=0;exec_argc<argc;exec_argc++)
exec_args[exec_argc]=strdup(argv[exec_argc]);
exec_args[exec_argc]=0;
signal( SIGSEGV, signal_handler );
signal( SIGFPE, signal_handler );
signal( SIGILL, signal_handler );
signal( SIGBUS, signal_handler );
signal( SIGABRT, signal_handler );
/* Catch SIGHUP etc so that we can respond to requests to do things */
signal( SIGHUP, signal_handler );
signal( SIGINT, signal_handler );
signal( SIGQUIT, signal_handler );
#endif
memabuseInit();
srandomdev();
server_save_argv(argc, argv);
if (argv[1]&&argv[1][0]!='-') {
/* First argument doesn't start with a dash, so assume it is for the new command line
parser. */

View File

@ -397,6 +397,7 @@ int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffe
unsigned char *transaction_id);
int requestNewHLR(char *did,char *pin,char *sid,int recvttl,struct sockaddr *recvaddr);
int server_pid();
void server_save_argv(int argc, const char *const *argv);
int server(char *backing_file);
void server_shutdown_check();
int server_create_stopfile();

164
server.c
View File

@ -28,6 +28,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define PIDFILE_NAME "servald.pid"
#define STOPFILE_NAME "servald.stop"
char *exec_args[128];
int exec_argc = 0;
int servalShutdown = 0;
static int server_getpid = 0;
unsigned char *hlr=NULL;
int hlr_size=0;
@ -37,6 +42,7 @@ FILE *i_f=NULL;
struct in_addr client_addr;
int client_port;
void signal_handler(int signal);
int getKeyring(char *s);
int createServerSocket();
int simpleServerMode();
@ -133,8 +139,27 @@ int server_pid()
return 0;
}
void server_save_argv(int argc, const char *const *argv)
{
/* Save our argv[] to use for relaunching */
for (exec_argc = 0; exec_argc != argc; ++exec_argc)
exec_args[exec_argc] = strdup(argv[exec_argc]);
exec_args[exec_argc] = 0;
}
int server(char *backing_file)
{
/* Catch sigsegv and other crash signals so that we can relaunch ourselves */
signal(SIGSEGV, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGBUS, signal_handler);
signal(SIGABRT, signal_handler);
/* Catch SIGHUP etc so that we can respond to requests to do things */
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
if (overlayMode)
{
/* Now find and initialise all the suitable network interfaces, i.e.,
@ -197,6 +222,7 @@ void server_shutdown_check()
static long long server_pid_time_ms = 0;
long long time_ms = overlay_gettime_ms();
if (server_pid_time_ms == 0 || time_ms - server_pid_time_ms > 1000) {
WHYF("time_ms=%lld", time_ms);
server_pid_time_ms = time_ms;
if (server_pid() != server_getpid) {
WHYF("Server pid file no longer contains pid=%d -- shutting down without cleanup", server_getpid);
@ -260,6 +286,144 @@ void serverCleanUp()
}
}
static void signame(char *buf, size_t len, int signal)
{
const char *desc = "";
switch(signal) {
#ifdef SIGHUP
case SIGHUP: desc = "HUP"; break;
#endif
#ifdef SIGINT
case SIGINT: desc = "INT"; break;
#endif
#ifdef SIGQUIT
case SIGQUIT: desc = "QUIT"; break;
#endif
#ifdef SIGILL
case SIGILL: desc = "ILL (not reset when caught)"; break;
#endif
#ifdef SIGTRAP
case SIGTRAP: desc = "TRAP (not reset when caught)"; break;
#endif
#ifdef SIGABRT
case SIGABRT: desc = "ABRT"; break;
#endif
#ifdef SIGPOLL
case SIGPOLL: desc = "POLL ([XSR] generated, not supported)"; break;
#endif
#ifdef SIGEMT
case SIGEMT: desc = "EMT"; break;
#endif
#ifdef SIGFPE
case SIGFPE: desc = "FPE"; break;
#endif
#ifdef SIGKILL
case SIGKILL: desc = "KILL (cannot be caught or ignored)"; break;
#endif
#ifdef SIGBUS
case SIGBUS: desc = "BUS"; break;
#endif
#ifdef SIGSEGV
case SIGSEGV: desc = "SEGV"; break;
#endif
#ifdef SIGSYS
case SIGSYS: desc = "SYS"; break;
#endif
#ifdef SIGPIPE
case SIGPIPE: desc = "PIPE"; break;
#endif
#ifdef SIGALRM
case SIGALRM: desc = "ALRM"; break;
#endif
#ifdef SIGTERM
case SIGTERM: desc = "TERM"; break;
#endif
#ifdef SIGURG
case SIGURG: desc = "URG"; break;
#endif
#ifdef SIGSTOP
case SIGSTOP: desc = "STOP"; break;
#endif
#ifdef SIGTSTP
case SIGTSTP: desc = "TSTP"; break;
#endif
#ifdef SIGCONT
case SIGCONT: desc = "CONT"; break;
#endif
#ifdef SIGCHLD
case SIGCHLD: desc = "CHLD"; break;
#endif
#ifdef SIGTTIN
case SIGTTIN: desc = "TTIN"; break;
#endif
#ifdef SIGTTOU
case SIGTTOU: desc = "TTOU"; break;
#endif
#ifdef SIGIO
#if SIGIO != SIGPOLL
case SIGIO: desc = "IO"; break;
#endif
#endif
#ifdef SIGXCPU
case SIGXCPU: desc = "XCPU"; break;
#endif
#ifdef SIGXFSZ
case SIGXFSZ: desc = "XFSZ"; break;
#endif
#ifdef SIGVTALRM
case SIGVTALRM: desc = "VTALRM"; break;
#endif
#ifdef SIGPROF
case SIGPROF: desc = "PROF"; break;
#endif
#ifdef SIGWINCH
case SIGWINCH: desc = "WINCH"; break;
#endif
#ifdef SIGINFO
case SIGINFO: desc = "INFO"; break;
#endif
#ifdef SIGUSR1
case SIGUSR1: desc = "USR1"; break;
#endif
#ifdef SIGUSR2
case SIGUSR2: desc = "USR2"; break;
#endif
}
snprintf(buf, len, "SIG%s (%d) %s", desc, signal, strsignal(signal));
buf[len - 1] = '\0';
}
void signal_handler(int signal)
{
char buf[80];
signame(buf, sizeof(buf), signal);
WHYF("Caught %s", buf);
switch (signal) {
case SIGQUIT:
serverCleanUp();
exit(0);
case SIGHUP:
case SIGINT:
/* Terminate the server process. The shutting down should be done from the main-line code
rather than here, so we first try to tell the mainline code to do so. If, however, this is
not the first time we have been asked to shut down, then we will do it here. */
server_shutdown_check();
WHY("Asking Serval process to shutdown cleanly");
servalShutdown = 1;
return;
}
/* oops - caught a bad signal -- exec() ourselves fresh */
WHY("Respawning");
if (sock>-1) close(sock);
int i;
for(i=0;i<overlay_interface_count;i++)
if (overlay_interfaces[i].fd>-1)
close(overlay_interfaces[i].fd);
execv(exec_args[0],exec_args);
/* Quit if the exec() fails */
exit(-3);
}
int getKeyring(char *backing_file)
{
if (!backing_file)