fixed path of mysql/errmsg.h (OSX compilation fix)
[NeonServV5.git] / src / signal.c
1 /* signal.c - NeonServ v5.6
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 "IOHandler.h"
22 #include "ConfigParser.h"
23
24 static void sigcrash();
25 static void sigexit();
26
27 void sighandler(int signum) {
28     putlog(LOGLEVEL_INFO, "Received Signal %d\n", signum);
29     signal(signum, SIG_DFL);
30     switch(signum) {
31         case SIGABRT:
32         case SIGTERM:
33         case SIGINT:
34             //normal shutdown
35             sigexit(signum);
36             break;
37         case SIGSEGV:
38         case SIGFPE:
39         case SIGILL:
40             //crash
41             sigcrash(signum);
42             break;
43     }
44     #ifdef WIN32
45     exit(signum);
46     #else
47     kill(getpid(), signum);
48     #endif
49 }
50
51 static void sigcrash(int signum) {
52     char coregen[MAXLEN];
53         coregen[0] = 0;
54     char *signame;
55     switch(signum) {
56         case SIGSEGV:
57             signame = "SIGSEGV";
58             break;
59         case SIGFPE:
60             signame = "SIGFPE";
61             break;
62         case SIGILL:
63             signame = "SIGILL";
64             break;
65         default:
66             signame = "SIGUNKNOWN";
67             break;
68     }
69     putlog(LOGLEVEL_ERROR, "NeonServ process crashed (%s)\n", signame);
70     #ifndef WIN32
71     char gcore[50];
72     sprintf(gcore, "gcore %u", getpid());
73     int sysretn = system(gcore); //generate core file
74     sprintf(coregen, "core file generated. (%d)", sysretn);
75     putlog(LOGLEVEL_ERROR | LOGLEVEL_INFO, "generated core file.\n");
76     #endif
77     char *alertchan = get_string_field("General.alertchan");
78     if(alertchan) {
79         struct ChanNode *channel = getChanByName(alertchan);
80         struct ClientSocket *client;
81         if(channel && (client = getChannelBot(channel, 0))) {
82             putsock(client, "PRIVMSG %s :\00304NeonServ received signal %d (%s). %s", alertchan, signum, signame, coregen);
83         }
84     }
85     //close all bots
86     struct ClientSocket *bot;
87     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
88         if((bot->flags & SOCKET_FLAG_CONNECTED)) {
89             iohandler_close(bot->iofd);
90             bot->flags &= ~(SOCKET_FLAG_CONNECTED | SOCKET_FLAG_READY);
91             bot->iofd = NULL;
92         }
93     }
94     putlog(LOGLEVEL_INFO, "hard shutdown...\n");
95     exit_daemon();
96     usleep(2000000);
97     //hard restart
98     restart_process();
99     exit(0);
100 }
101
102 static void sigexit(int signum) {
103     cleanup();
104     exit_daemon();
105     exit(0);
106 }