*** VERSION 5.5.0 ***
[NeonServV5.git] / src / signal.c
1 /* signal.c - NeonServ v5.5
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "signal.h"
18 #include "bots.h"
19 #include "ChanNode.h"
20 #include "ClientSocket.h"
21 #include "ConfigParser.h"
22
23 static void sigcrash();
24 static void sigexit();
25
26 void sighandler(int signum) {
27     putlog(LOGLEVEL_INFO, "Received Signal %d\n", signum);
28     signal(signum, SIG_DFL);
29     switch(signum) {
30         case SIGABRT:
31         case SIGTERM:
32         case SIGINT:
33             //normal shutdown
34             sigexit(signum);
35             break;
36         case SIGSEGV:
37         case SIGFPE:
38         case SIGILL:
39             //crash
40             sigcrash(signum);
41             break;
42     }
43     #ifdef WIN32
44     exit(signum);
45     #else
46     kill(getpid(), signum);
47     #endif
48 }
49
50 static void sigcrash(int signum) {
51     char coregen[MAXLEN];
52         coregen[0] = 0;
53     char *signame;
54     switch(signum) {
55         case SIGSEGV:
56             signame = "SIGSEGV";
57             break;
58         case SIGFPE:
59             signame = "SIGFPE";
60             break;
61         case SIGILL:
62             signame = "SIGILL";
63             break;
64         default:
65             signame = "SIGUNKNOWN";
66             break;
67     }
68     putlog(LOGLEVEL_ERROR, "NeonServ process crashed (%s)\n", signame);
69     #ifndef WIN32
70     char gcore[50];
71     sprintf(gcore, "gcore %u", getpid());
72     int sysretn = system(gcore); //generate core file
73     sprintf(coregen, "core file generated. (%d)", sysretn);
74     putlog(LOGLEVEL_ERROR | LOGLEVEL_INFO, "generated core file.\n");
75     #endif
76     char *alertchan = get_string_field("General.alertchan");
77     if(alertchan) {
78         struct ChanNode *channel = getChanByName(alertchan);
79         struct ClientSocket *client;
80         if(channel && (client = getChannelBot(channel, 0))) {
81             putsock(client, "PRIVMSG %s :\00304NeonServ received signal %d (%s). %s", alertchan, signum, signame, coregen);
82         }
83     }
84     //close all bots
85     struct ClientSocket *bot;
86     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
87         if((bot->flags & SOCKET_FLAG_CONNECTED)) {
88             close(bot->sock);
89             bot->flags &= SOCKET_FLAG_CONNECTED;
90         }
91     }
92     putlog(LOGLEVEL_INFO, "hard shutdown...\n");
93     exit_daemon();
94     usleep(2000000);
95     //hard restart
96     restart_process();
97     exit(0);
98 }
99
100 static void sigexit(int signum) {
101     cleanup();
102     exit_daemon();
103     exit(0);
104 }