signals.cpp

main 221 lines · 5.6 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "otpch.h"
21#include <csignal>
22
23#include "signals.h"
24#include "tasks.h"
25#include "game.h"
26#include "actions.h"
27#include "configmanager.h"
28#include "spells.h"
29#include "talkaction.h"
30#include "movement.h"
31#include "weapons.h"
32#include "raids.h"
33#include "quests.h"
34#include "mounts.h"
35#include "auras.h"
36#include "wings.h"
37#include "globalevent.h"
38#include "monster.h"
39#include "events.h"
40#include "scheduler.h"
41#include "databasetasks.h"
42
43
44extern Scheduler g_scheduler;
45extern DatabaseTasks g_databaseTasks;
46extern Dispatcher g_dispatcher;
47
48extern ConfigManager g_config;
49extern Actions* g_actions;
50extern Monsters g_monsters;
51extern TalkActions* g_talkActions;
52extern MoveEvents* g_moveEvents;
53extern Spells* g_spells;
54extern Weapons* g_weapons;
55extern Game g_game;
56extern CreatureEvents* g_creatureEvents;
57extern GlobalEvents* g_globalEvents;
58extern Events* g_events;
59extern Chat* g_chat;
60extern LuaEnvironment g_luaEnvironment;
61
62using ErrorCode = boost::system::error_code;
63
64Signals::Signals(boost::asio::io_service& service) :
65 set(service)
66{
67 set.add(SIGINT);
68 set.add(SIGTERM);
69#ifndef _WIN32
70 set.add(SIGUSR1);
71 set.add(SIGHUP);
72#else
73 // This must be a blocking call as Windows calls it in a new thread and terminates
74 // the process when the handler returns (or after 5 seconds, whichever is earlier).
75 // On Windows it is called in a new thread.
76 signal(SIGBREAK, dispatchSignalHandler);
77#endif
78
79 asyncWait();
80}
81
82void Signals::asyncWait()
83{
84 set.async_wait([this] (ErrorCode err, int signal) {
85 if (err) {
86 std::cerr << "Signal handling error: " << err.message() << std::endl;
87 return;
88 }
89 dispatchSignalHandler(signal);
90 asyncWait();
91 });
92}
93
94// On Windows this function does not need to be signal-safe,
95// as it is called in a new thread.
96// https://github.com/otland/forgottenserver/pull/2473
97void Signals::dispatchSignalHandler(int signal)
98{
99 switch(signal) {
100 case SIGINT: //Shuts the server down
101 g_dispatcher.addTask(createTask(sigintHandler));
102 break;
103 case SIGTERM: //Shuts the server down
104 g_dispatcher.addTask(createTask(sigtermHandler));
105 break;
106#ifndef _WIN32
107 case SIGHUP: //Reload config/data
108 g_dispatcher.addTask(createTask(sighupHandler));
109 break;
110 case SIGUSR1: //Saves game state
111 g_dispatcher.addTask(createTask(sigusr1Handler));
112 break;
113#else
114 case SIGBREAK: //Shuts the server down
115 g_dispatcher.addTask(createTask(sigbreakHandler));
116 // hold the thread until other threads end
117 g_scheduler.join();
118 g_databaseTasks.join();
119 g_dispatcher.join();
120 break;
121#endif
122 default:
123 break;
124 }
125}
126
127void Signals::sigbreakHandler()
128{
129 //Dispatcher thread
130 std::cout << "SIGBREAK received, shutting game server down..." << std::endl;
131 g_game.setGameState(GAME_STATE_SHUTDOWN);
132}
133
134void Signals::sigtermHandler()
135{
136 //Dispatcher thread
137 std::cout << "SIGTERM received, shutting game server down..." << std::endl;
138 g_game.setGameState(GAME_STATE_SHUTDOWN);
139}
140
141void Signals::sigusr1Handler()
142{
143 //Dispatcher thread
144 std::cout << "SIGUSR1 received, saving the game state..." << std::endl;
145 g_game.saveGameState();
146}
147
148void Signals::sighupHandler()
149{
150 //Dispatcher thread
151 std::cout << "SIGHUP received, reloading config files..." << std::endl;
152
153 g_actions->reload();
154 std::cout << "Reloaded actions." << std::endl;
155
156 g_config.reload();
157 std::cout << "Reloaded config." << std::endl;
158
159 g_creatureEvents->reload();
160 std::cout << "Reloaded creature scripts." << std::endl;
161
162 g_moveEvents->reload();
163 std::cout << "Reloaded movements." << std::endl;
164
165 Npcs::reload();
166 std::cout << "Reloaded npcs." << std::endl;
167
168 g_game.raids.reload();
169 g_game.raids.startup();
170 std::cout << "Reloaded raids." << std::endl;
171
172 g_spells->reload();
173 std::cout << "Reloaded monsters." << std::endl;
174
175 g_monsters.reload();
176 std::cout << "Reloaded spells." << std::endl;
177
178 g_talkActions->reload();
179 std::cout << "Reloaded talk actions." << std::endl;
180
181 Item::items.reload();
182 std::cout << "Reloaded items." << std::endl;
183
184 g_weapons->reload();
185 g_weapons->loadDefaults();
186 std::cout << "Reloaded weapons." << std::endl;
187
188 g_game.quests.reload();
189 std::cout << "Reloaded quests." << std::endl;
190
191 g_game.mounts.reload();
192 std::cout << "Reloaded mounts." << std::endl;
193
194 g_game.auras.reload();
195 std::cout << "Reloaded auras." << std::endl;
196
197 g_game.wings.reload();
198 std::cout << "Reloaded wings." << std::endl;
199
200 g_globalEvents->reload();
201 std::cout << "Reloaded globalevents." << std::endl;
202
203 g_events->load();
204 std::cout << "Reloaded events." << std::endl;
205
206 g_chat->load();
207 std::cout << "Reloaded chatchannels." << std::endl;
208
209 g_luaEnvironment.loadFile("data/global.lua");
210 std::cout << "Reloaded global.lua." << std::endl;
211
212 lua_gc(g_luaEnvironment.getLuaState(), LUA_GCCOLLECT, 0);
213}
214
215void Signals::sigintHandler()
216{
217 //Dispatcher thread
218 std::cout << "SIGINT received, shutting game server down..." << std::endl;
219 g_game.setGameState(GAME_STATE_SHUTDOWN);
220}
221
Top