848828c4a27779c95f6fa42c1eeff527aa800abc
[NeonServV5.git] / src / signal.c
1 /* signal.c - NeonServ v5.3
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", 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     kill(getpid(), signum);
44 }
45
46 static void sigcrash(int signum) {
47     char *coregen = "";
48     char *signame;
49     switch(signum) {
50         case SIGSEGV:
51             signame = "SIGSEGV";
52             break;
53         case SIGFPE:
54             signame = "SIGFPE";
55             break;
56         case SIGILL:
57             signame = "SIGILL";
58             break;
59         default:
60             signame = "SIGUNKNOWN";
61             break;
62     }
63     putlog(LOGLEVEL_ERROR, "NeonServ process crashed (%s)", signame);
64     #ifndef WIN32
65     char gcore[50];
66     sprintf(gcore, "gcore %u", getpid());
67     system(gcore); //generate core file
68     coregen = "core file generated.";
69     putlog(LOGLEVEL_ERROR | LOGLEVEL_INFO, "generated core file.");
70     #endif
71     char *alertchan = get_string_field("General.alertchan");
72     if(alertchan) {
73         struct ChanNode *channel = getChanByName(alertchan);
74         struct ClientSocket *client;
75         if(channel && (client = getChannelBot(channel, 0))) {
76             putsock(client, "PRIVMSG %s :\00304NeonServ received signal %d (%s). %s", alertchan, signum, signame, coregen);
77         }
78     }
79     //close all bots
80     struct ClientSocket *bot;
81     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
82         if((bot->flags & SOCKET_FLAG_CONNECTED)) {
83             close(bot->sock);
84             bot->flags &= SOCKET_FLAG_CONNECTED;
85         }
86     }
87     putlog(LOGLEVEL_INFO, "hard shutdown...");
88     exit_daemon();
89     sleep(1);
90     //hard restart
91     restart_process();
92 }
93
94 static void sigexit(int signum) {
95     cleanup();
96     exit_daemon();
97     exit(0);
98 }