added signal handler
[NeonServV5.git] / src / signal.c
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();
+}