From db9df7a1356859ffb8dcca001317940c92a80045 Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 29 Jan 2012 20:47:07 +0100 Subject: [PATCH] added signal handler --- Makefile.am | 1 + src/main.c | 35 ++++++++++++++------ src/main.h | 2 ++ src/signal.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/signal.h | 24 ++++++++++++++ 5 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 src/signal.c create mode 100644 src/signal.h diff --git a/Makefile.am b/Makefile.am index 47222e6..2d4f78a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,7 @@ neonserv_SOURCES = src/version.c \ src/EventLogger.c \ src/IRCEvents.c \ src/main.c \ + src/signal.c \ src/ChanNode.c \ src/IRCParser.c \ src/ClientSocket.c \ diff --git a/src/main.c b/src/main.c index b86633e..7e1839f 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ */ #include "main.h" +#include "signal.h" #include "ClientSocket.h" #include "UserNode.h" #include "ChanNode.h" @@ -44,6 +45,8 @@ static int statistics_requested_lusers = 0; int statistics_enabled; TIMEQ_CALLBACK(main_statistics); TIMEQ_CALLBACK(main_checkauths); +static int process_argc; +static char **process_argv; #ifdef HAVE_THREADS int running_threads; pthread_mutex_t cache_sync; @@ -136,6 +139,15 @@ int getCurrentThreadID() { int main(int argc, char *argv[]) { main: + process_argv = argv; + process_argc = argc; + + signal(SIGABRT, sighandler); + signal(SIGFPE, sighandler); + signal(SIGILL, sighandler); + signal(SIGINT, sighandler); + signal(SIGSEGV, sighandler); + signal(SIGTERM, sighandler); start_time = time(0); @@ -225,20 +237,23 @@ main: #endif cleanup(); if(hard_restart) { - /* Append a NULL to the end of argv[]. */ - char **restart_argv = (char **)alloca((argc + 1) * sizeof(char *)); - memcpy(restart_argv, argv, argc * sizeof(char *)); - restart_argv[argc] = NULL; - - #ifdef WIN32 - execv(argv[0], (const char * const*)restart_argv); - #else - execv(argv[0], restart_argv); - #endif + restart_process(); } goto main; } +void restart_process() { + /* Append a NULL to the end of argv[]. */ + char **restart_argv = (char **)alloca((process_argc + 1) * sizeof(char *)); + memcpy(restart_argv, process_argv, process_argc * sizeof(char *)); + restart_argv[process_argc] = NULL; + #ifdef WIN32 + execv(process_argv[0], (const char * const*)restart_argv); + #else + execv(process_argv[0], restart_argv); + #endif +} + int stricmp (const char *s1, const char *s2) { if (s1 == NULL) return s2 == NULL ? 0 : -(*s2); diff --git a/src/main.h b/src/main.h index d14869e..329f391 100644 --- a/src/main.h +++ b/src/main.h @@ -147,6 +147,8 @@ int getCurrentThreadID(); int stricmp (const char *s1, const char *s2); int stricmplen (const char *s1, const char *s2, int len); +void restart_process(); +void cleanup(); void restart_bot(int do_hard_restart); void stop_bot(); void reload_config(); diff --git a/src/signal.c b/src/signal.c new file mode 100644 index 0000000..d5431da --- /dev/null +++ b/src/signal.c @@ -0,0 +1,91 @@ +/* signal.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "signal.h" +#include "bots.h" +#include "ChanNode.h" +#include "ClientSocket.h" +#include "ConfigParser.h" + +static void sigcrash(); +static void sigexit(); + +void sighandler(int signum) { + signal(signum, SIG_DFL); + switch(signum) { + case SIGABRT: + case SIGTERM: + case SIGINT: + //normal shutdown + sigexit(signum); + break; + case SIGSEGV: + case SIGFPE: + case SIGILL: + //crash + sigcrash(signum); + break; + } + kill(getpid(), signum); +} + +static void sigcrash(int signum) { + char *coregen = ""; + #ifndef WIN32 + char gcore[50]; + sprintf(gcore, "gcore %u", getpid()); + system(gcore); //generate core file + coregen = "core file generated."; + #endif + char *signame; + switch(signum) { + case SIGSEGV: + signame = "SIGSEGV"; + break; + case SIGFPE: + signame = "SIGFPE"; + break; + case SIGILL: + signame = "SIGILL"; + break; + default: + signame = "SIGUNKNOWN"; + break; + } + char *alertchan = get_string_field("General.alertchan"); + if(alertchan) { + struct ChanNode *channel = getChanByName(alertchan); + struct ClientSocket *client; + if(channel && (client = getChannelBot(channel, 0))) { + putsock(client, "PRIVMSG %s :\00304NeonServ received signal %d (%s). %s", alertchan, signum, signame, coregen); + } + } + //close all bots + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if((bot->flags & SOCKET_FLAG_CONNECTED)) { + close(bot->sock); + bot->flags &= SOCKET_FLAG_CONNECTED; + } + } + sleep(1); + //hard restart + restart_process(); +} + +static void sigexit(int signum) { + cleanup(); +} diff --git a/src/signal.h b/src/signal.h new file mode 100644 index 0000000..cc7c829 --- /dev/null +++ b/src/signal.h @@ -0,0 +1,24 @@ +/* signal.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _signal_h +#define _signal_h + +#include "main.h" + +void sighandler(int signum); + +#endif \ No newline at end of file -- 2.20.1