OSDN Git Service

39bb203e76672013bb0b64c64fa5a59fa15df395
[hengband/hengband.git] / src / io / signal-handlers.c
1 /*!
2  * @file signal-handlers.c
3  * @brief シグナルハンドラの管理 / Controlling signal handlers
4  * @date 2020/02/23
5  * @author Hourier
6  */
7
8 #include "io/signal-handlers.h"
9 #include "core.h"
10 #include "core/game-closer.h"
11 #include "save.h"
12 #include "world.h"
13 #include "gameterm.h"
14 #include "io/write-diary.h"
15 #include "cmd/cmd-dump.h"
16 #include "floor-events.h"
17
18 s16b signal_count;              /* Hack -- Count interupts */
19
20 #ifdef HANDLE_SIGNALS
21
22 #include <signal.h>
23
24 /*!
25  * @brief OSからのシグナルを受けてサスペンド状態に入る /
26  * Handle signals -- suspend
27  * @param sig 受け取ったシグナル
28  * @details
29  * Actually suspend the game, and then resume cleanly
30  */
31 static void handle_signal_suspend(int sig)
32 {
33         (void)signal(sig, SIG_IGN);
34 #ifdef SIGSTOP
35         Term_fresh();
36         Term_xtra(TERM_XTRA_ALIVE, 0);
37         (void)kill(0, SIGSTOP);
38         Term_xtra(TERM_XTRA_ALIVE, 1);
39         Term_redraw();
40         Term_fresh();
41 #endif
42         (void)signal(sig, handle_signal_suspend);
43 }
44
45
46 /*!
47  * todo ここにplayer_typeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
48  * @brief OSからのシグナルを受けて中断、終了する /
49  * Handle signals -- simple (interrupt and quit)
50  * @param sig 受け取ったシグナル
51  * @details
52  * <pre>
53  * This function was causing a *huge* number of problems, so it has
54  * been simplified greatly.  We keep a global variable which counts
55  * the number of times the user attempts to kill the process, and
56  * we commit suicide if the user does this a certain number of times.
57  * We attempt to give "feedback" to the user as he approaches the
58  * suicide thresh-hold, but without penalizing accidental keypresses.
59  * To prevent messy accidents, we should reset this global variable
60  * whenever the user enters a keypress, or something like that.
61  * </pre>
62  */
63 static void handle_signal_simple(int sig)
64 {
65         (void)signal(sig, SIG_IGN);
66         if (!current_world_ptr->character_generated || current_world_ptr->character_saved)
67                 quit(NULL);
68
69         signal_count++;
70         if (p_ptr->is_dead)
71         {
72                 (void)strcpy(p_ptr->died_from, _("強制終了", "Abortion"));
73                 forget_lite(p_ptr->current_floor_ptr);
74                 forget_view(p_ptr->current_floor_ptr);
75                 clear_mon_lite(p_ptr->current_floor_ptr);
76                 close_game(p_ptr);
77                 quit(_("強制終了", "interrupt"));
78         }
79         else if (signal_count >= 5)
80         {
81                 (void)strcpy(p_ptr->died_from, _("強制終了中", "Interrupting"));
82                 forget_lite(p_ptr->current_floor_ptr);
83                 forget_view(p_ptr->current_floor_ptr);
84                 clear_mon_lite(p_ptr->current_floor_ptr);
85                 p_ptr->playing = FALSE;
86                 p_ptr->is_dead = TRUE;
87                 p_ptr->leaving = TRUE;
88                 close_game(p_ptr);
89                 quit(_("強制終了", "interrupt"));
90         }
91         else if (signal_count >= 4)
92         {
93                 Term_xtra(TERM_XTRA_NOISE, 0);
94                 Term_erase(0, 0, 255);
95                 Term_putstr(0, 0, -1, TERM_WHITE, _("熟慮の上の自殺!", "Contemplating suicide!"));
96                 Term_fresh();
97         }
98         else if (signal_count >= 2)
99         {
100                 Term_xtra(TERM_XTRA_NOISE, 0);
101         }
102
103         (void)signal(sig, handle_signal_simple);
104 }
105
106
107 /*!
108  * todo ここにp_ptrを追加すると関数ポインタ周りの収拾がつかなくなるので保留
109  * @brief OSからのシグナルを受けて強制終了する /
110  * Handle signal -- abort, kill, etc
111  * @param sig 受け取ったシグナル
112  * @return なし
113  * @details
114  * <pre>
115  * This function was causing a *huge* number of problems, so it has
116  * been simplified greatly.  We keep a global variable which counts
117  * the number of times the user attempts to kill the process, and
118  * we commit suicide if the user does this a certain number of times.
119  * We attempt to give "feedback" to the user as he approaches the
120  * suicide thresh-hold, but without penalizing accidental keypresses.
121  * To prevent messy accidents, we should reset this global variable
122  * whenever the user enters a keypress, or something like that.
123  * </pre>
124  */
125 static void handle_signal_abort(int sig)
126 {
127         int wid, hgt;
128         Term_get_size(&wid, &hgt);
129
130         (void)signal(sig, SIG_IGN);
131         if (!current_world_ptr->character_generated || current_world_ptr->character_saved) quit(NULL);
132
133         forget_lite(p_ptr->current_floor_ptr);
134         forget_view(p_ptr->current_floor_ptr);
135         clear_mon_lite(p_ptr->current_floor_ptr);
136
137         Term_erase(0, hgt - 1, 255);
138         Term_putstr(0, hgt - 1, -1, TERM_RED,
139                 _("恐ろしいソフトのバグが飛びかかってきた!", "A gruesome software bug LEAPS out at you!"));
140
141         Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ...", "Panic save..."));
142
143         exe_write_diary(p_ptr, DIARY_GAMESTART, 0, _("----ゲーム異常終了----", "-- Tried Panic Save and Aborted Game --"));
144         Term_fresh();
145
146         p_ptr->panic_save = 1;
147         (void)strcpy(p_ptr->died_from, _("(緊急セーブ)", "(panic save)"));
148
149         signals_ignore_tstp();
150
151         if (save_player(p_ptr))
152         {
153                 Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ成功!", "Panic save succeeded!"));
154         }
155         else
156         {
157                 Term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ失敗!", "Panic save failed!"));
158         }
159
160         Term_fresh();
161         quit(_("ソフトのバグ", "software bug"));
162 }
163
164
165 /*!
166  * @brief OSからのSIGTSTPシグナルを無視する関数 /
167  * Ignore SIGTSTP signals (keyboard suspend)
168  * @return なし
169  * @details
170  */
171 void signals_ignore_tstp(void)
172 {
173 #ifdef SIGTSTP
174         (void)signal(SIGTSTP, SIG_IGN);
175 #endif
176 }
177
178
179 /*!
180  * @brief OSからのSIGTSTPシグナルハンドラ /
181  * Handle SIGTSTP signals (keyboard suspend)
182  * @return なし
183  * @details
184  */
185 void signals_handle_tstp(void)
186 {
187 #ifdef SIGTSTP
188         (void)signal(SIGTSTP, handle_signal_suspend);
189 #endif
190 }
191
192
193 /*!
194  * @brief OSからのシグナルハンドルを初期化する /
195  * Prepare to handle the relevant signals
196  * @return なし
197  * @details
198  */
199 void signals_init(void)
200 {
201 #ifdef SIGHUP
202         (void)signal(SIGHUP, SIG_IGN);
203 #endif
204
205 #ifdef SIGTSTP
206         (void)signal(SIGTSTP, handle_signal_suspend);
207 #endif
208
209 #ifdef SIGINT
210         (void)signal(SIGINT, handle_signal_simple);
211 #endif
212
213 #ifdef SIGQUIT
214         (void)signal(SIGQUIT, handle_signal_simple);
215 #endif
216
217 #ifdef SIGFPE
218         (void)signal(SIGFPE, handle_signal_abort);
219 #endif
220
221 #ifdef SIGILL
222         (void)signal(SIGILL, handle_signal_abort);
223 #endif
224
225 #ifdef SIGTRAP
226         (void)signal(SIGTRAP, handle_signal_abort);
227 #endif
228
229 #ifdef SIGIOT
230         (void)signal(SIGIOT, handle_signal_abort);
231 #endif
232
233 #ifdef SIGKILL
234         (void)signal(SIGKILL, handle_signal_abort);
235 #endif
236
237 #ifdef SIGBUS
238         (void)signal(SIGBUS, handle_signal_abort);
239 #endif
240
241 #ifdef SIGSEGV
242         (void)signal(SIGSEGV, handle_signal_abort);
243 #endif
244
245 #ifdef SIGTERM
246         (void)signal(SIGTERM, handle_signal_abort);
247 #endif
248
249 #ifdef SIGPIPE
250         (void)signal(SIGPIPE, handle_signal_abort);
251 #endif
252
253 #ifdef SIGEMT
254         (void)signal(SIGEMT, handle_signal_abort);
255 #endif
256
257 #ifdef SIGDANGER
258         (void)signal(SIGDANGER, handle_signal_abort);
259 #endif
260
261 #ifdef SIGSYS
262         (void)signal(SIGSYS, handle_signal_abort);
263 #endif
264
265 #ifdef SIGXCPU
266         (void)signal(SIGXCPU, handle_signal_abort);
267 #endif
268
269 #ifdef SIGPWR
270         (void)signal(SIGPWR, handle_signal_abort);
271 #endif
272 }
273
274 #else
275
276 /*!
277  * @brief ダミー /
278  * Do nothing
279  */
280 void signals_ignore_tstp(void)
281 {
282 }
283
284
285 /*!
286  * @brief ダミー /
287  * Do nothing
288  */
289 void signals_handle_tstp(void)
290 {
291 }
292
293
294 /*!
295  * @brief ダミー /
296  * Do nothing
297  */
298 void signals_init(void)
299 {
300 }
301 #endif