2 * @file signal-handlers.c
3 * @brief シグナルハンドラの管理 / Controlling signal handlers
8 #include "io/signal-handlers.h"
9 #include "cmd-io/cmd-dump.h"
10 #include "core/game-closer.h"
11 #include "floor/floor-events.h"
12 #include "game-option/cheat-options.h"
13 #include "io/write-diary.h"
14 #include "monster-floor/monster-lite.h"
15 #include "save/save.h"
16 #include "system/player-type-definition.h"
17 #include "system/system-variables.h"
18 #include "term/term-color-types.h"
19 #include "world/world.h"
21 int16_t signal_count; /* Hack -- Count interupts */
26 * @brief OSからのシグナルを受けてサスペンド状態に入る /
27 * Handle signals -- suspend
28 * @param sig 受け取ったシグナル
30 * Actually suspend the game, and then resume cleanly
32 static void handle_signal_suspend(int sig)
34 (void)signal(sig, SIG_IGN);
37 term_xtra(TERM_XTRA_ALIVE, 0);
38 (void)kill(0, SIGSTOP);
39 term_xtra(TERM_XTRA_ALIVE, 1);
43 (void)signal(sig, handle_signal_suspend);
47 * @brief OSからのシグナルを受けて中断、終了する /
48 * Handle signals -- simple (interrupt and quit)
49 * @param sig 受け取ったシグナル
52 * This function was causing a *huge* number of problems, so it has
53 * been simplified greatly. We keep a global variable which counts
54 * the number of times the user attempts to kill the process, and
55 * we commit suicide if the user does this a certain number of times.
56 * We attempt to give "feedback" to the user as he approaches the
57 * suicide thresh-hold, but without penalizing accidental keypresses.
58 * To prevent messy accidents, we should reset this global variable
59 * whenever the user enters a keypress, or something like that.
61 * @todo ここにPlayerTypeを追加すると関数ポインタ周りの収拾がつかなくなるので保留
63 static void handle_signal_simple(int sig)
65 (void)signal(sig, SIG_IGN);
66 if (!w_ptr->character_generated || w_ptr->character_saved) {
72 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);
77 quit(_("強制終了", "interrupt"));
78 } else if (signal_count >= 5) {
79 p_ptr->died_from = _("強制終了中", "Interrupting");
80 forget_lite(p_ptr->current_floor_ptr);
81 forget_view(p_ptr->current_floor_ptr);
82 clear_mon_lite(p_ptr->current_floor_ptr);
83 p_ptr->playing = false;
84 if (!cheat_immortal) {
85 p_ptr->is_dead = true;
87 p_ptr->leaving = true;
89 quit(_("強制終了", "interrupt"));
90 } else if (signal_count >= 4) {
91 term_xtra(TERM_XTRA_NOISE, 0);
93 term_putstr(0, 0, -1, TERM_WHITE, _("熟慮の上の自殺!", "Contemplating suicide!"));
95 } else if (signal_count >= 2) {
96 term_xtra(TERM_XTRA_NOISE, 0);
99 (void)signal(sig, handle_signal_simple);
103 * @brief OSからのシグナルを受けて強制終了する /
104 * Handle signal -- abort, kill, etc
105 * @param sig 受け取ったシグナル
108 * This function was causing a *huge* number of problems, so it has
109 * been simplified greatly. We keep a global variable which counts
110 * the number of times the user attempts to kill the process, and
111 * we commit suicide if the user does this a certain number of times.
112 * We attempt to give "feedback" to the user as he approaches the
113 * suicide thresh-hold, but without penalizing accidental keypresses.
114 * To prevent messy accidents, we should reset this global variable
115 * whenever the user enters a keypress, or something like that.
117 * @todo ここにp_ptrを追加すると関数ポインタ周りの収拾がつかなくなるので保留
119 static void handle_signal_abort(int sig)
122 term_get_size(&wid, &hgt);
124 (void)signal(sig, SIG_IGN);
125 if (!w_ptr->character_generated || w_ptr->character_saved) {
129 forget_lite(p_ptr->current_floor_ptr);
130 forget_view(p_ptr->current_floor_ptr);
131 clear_mon_lite(p_ptr->current_floor_ptr);
133 term_erase(0, hgt - 1);
134 term_putstr(0, hgt - 1, -1, TERM_RED, _("恐ろしいソフトのバグが飛びかかってきた!", "A gruesome software bug LEAPS out at you!"));
136 term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ...", "Panic save..."));
138 exe_write_diary(p_ptr, DiaryKind::GAMESTART, 0, _("----ゲーム異常終了----", "-- Tried Panic Save and Aborted Game --"));
141 p_ptr->panic_save = 1;
142 p_ptr->died_from = _("(緊急セーブ)", "(panic save)");
144 signals_ignore_tstp();
146 if (save_player(p_ptr, SaveType::CLOSE_GAME)) {
147 term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ成功!", "Panic save succeeded!"));
149 term_putstr(45, hgt - 1, -1, TERM_RED, _("緊急セーブ失敗!", "Panic save failed!"));
153 quit(_("ソフトのバグ", "software bug"));
157 * @brief OSからのSIGTSTPシグナルを無視する関数 /
158 * Ignore SIGTSTP signals (keyboard suspend)
161 void signals_ignore_tstp(void)
164 (void)signal(SIGTSTP, SIG_IGN);
169 * @brief OSからのSIGTSTPシグナルハンドラ /
170 * Handle SIGTSTP signals (keyboard suspend)
173 void signals_handle_tstp(void)
176 (void)signal(SIGTSTP, handle_signal_suspend);
181 * @brief OSからのシグナルハンドルを初期化する /
182 * Prepare to handle the relevant signals
185 void signals_init(void)
188 (void)signal(SIGHUP, SIG_IGN);
192 (void)signal(SIGTSTP, handle_signal_suspend);
196 (void)signal(SIGINT, handle_signal_simple);
200 (void)signal(SIGQUIT, handle_signal_simple);
204 (void)signal(SIGFPE, handle_signal_abort);
208 (void)signal(SIGILL, handle_signal_abort);
212 (void)signal(SIGTRAP, handle_signal_abort);
216 (void)signal(SIGIOT, handle_signal_abort);
220 (void)signal(SIGBUS, handle_signal_abort);
224 (void)signal(SIGSEGV, handle_signal_abort);
228 (void)signal(SIGTERM, handle_signal_abort);
232 (void)signal(SIGPIPE, handle_signal_abort);
236 (void)signal(SIGEMT, handle_signal_abort);
240 (void)signal(SIGDANGER, handle_signal_abort);
244 (void)signal(SIGSYS, handle_signal_abort);
248 (void)signal(SIGXCPU, handle_signal_abort);
252 (void)signal(SIGPWR, handle_signal_abort);