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