added signal handler
authorpk910 <philipp@zoelle1.de>
Sun, 29 Jan 2012 19:47:07 +0000 (20:47 +0100)
committerpk910 <philipp@zoelle1.de>
Sun, 29 Jan 2012 19:59:27 +0000 (20:59 +0100)
Makefile.am
src/main.c
src/main.h
src/signal.c [new file with mode: 0644]
src/signal.h [new file with mode: 0644]

index 47222e6cf91326166f898f35317f9f8e561fe2de..2d4f78a3ba92620fc3acb1aa444a12491a41b40c 100644 (file)
@@ -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 \
index b86633e7e01536e4df08fa7fb657f429dca994fc..7e1839f1c9ca27127ef907388c861e19c4a3ac3d 100644 (file)
@@ -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);
index d14869e11564df1426fe6b2a56967b18659f8bd3..329f391ad4f8c0120c0aed51f8a70f9c0c8de80b 100644 (file)
@@ -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 (file)
index 0000000..d5431da
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..cc7c829
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _signal_h
+#define _signal_h
+
+#include "main.h"
+
+void sighandler(int signum);
+
+#endif
\ No newline at end of file