diff options
-rw-r--r-- | crawl-ref/source/acr.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/cio.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/directn.cc | 26 | ||||
-rw-r--r-- | crawl-ref/source/effects.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/libunix.cc | 52 | ||||
-rw-r--r-- | crawl-ref/source/libunix.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/message.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/religion.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/spells3.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 18 | ||||
-rw-r--r-- | crawl-ref/source/view.cc | 10 |
11 files changed, 147 insertions, 12 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index d325db5194..585ddc1b8f 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -885,6 +885,11 @@ static void _center_cursor() // static void _input() { +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + if (crawl_state.seen_hups) + sighup_save_and_exit(); +#endif + crawl_state.clear_mon_acting(); religion_turn_start(); @@ -1029,6 +1034,11 @@ static void _input() #endif const command_type cmd = _get_next_cmd(); +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + if (crawl_state.seen_hups) + sighup_save_and_exit(); +#endif + crawl_state.waiting_for_command = false; if (cmd != CMD_PREV_CMD_AGAIN && cmd != CMD_REPEAT_CMD @@ -2479,6 +2489,7 @@ static void _check_banished() if (you.level_type != LEVEL_ABYSS) { mpr("You are cast into the Abyss!"); + more(); banished(DNGN_ENTER_ABYSS, you.banished_by); } you.banished_by.clear(); diff --git a/crawl-ref/source/cio.cc b/crawl-ref/source/cio.cc index c420553b36..60e1d715e1 100644 --- a/crawl-ref/source/cio.cc +++ b/crawl-ref/source/cio.cc @@ -426,6 +426,15 @@ int line_reader::read_line(bool clear_previous) { int ch = getchm(c_getch); +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // Don't return a partial string if a HUP signal interrupted things + if (crawl_state.seen_hups) + { + buffer[0] = '\0'; + return (0); + } +#endif + if (keyfn) { int whattodo = (*keyfn)(ch); diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc index 092e6b14b0..1e162049f6 100644 --- a/crawl-ref/source/directn.cc +++ b/crawl-ref/source/directn.cc @@ -138,6 +138,19 @@ void direction_choose_compass( dist& moves, targeting_behaviour *beh) { const command_type key_command = beh->get_command(); +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // If we've received a HUP signal then the user can't choose a + // target. + if (crawl_state.seen_hups) + { + moves.isValid = false; + moves.isCancel = true; + + mpr("Targetting interrupted by HUP signal.", MSGCH_ERROR); + return; + } +#endif + #ifdef USE_TILE if (key_command == CMD_TARGET_MOUSE_MOVE) { @@ -1064,6 +1077,19 @@ void direction(dist& moves, targeting_type restricts, while (true) { +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // If we've received a HUP signal then the user can't choose a + // target. + if (crawl_state.seen_hups) + { + moves.isValid = false; + moves.isCancel = true; + + mpr("Targetting interrupted by HUP signal.", MSGCH_ERROR); + return; + } +#endif + bool allow_out_of_range = false; // Prompts might get scrolled off if you have too few lines available. diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 02240e1c3e..7f994303df 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -1575,7 +1575,18 @@ bool acquirement(object_class_type class_wanted, int agent, canned_msg(MSG_OK); return (false); } - break; + +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // If we've gotten a HUP signal then the player will be unable + // to make a selection. + if (crawl_state.seen_hups) + { + mpr("Acquirement interrupted by HUP signal.", MSGCH_ERROR); + you.turn_is_over = false; + return (false); + } +#endif + break; } } diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index 830f03edcb..20dd071ca8 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -31,6 +31,7 @@ REVISION("$Rev$"); #include "defines.h" #include "cio.h" +#include "delay.h" #include "enum.h" #include "externs.h" #include "files.h" @@ -330,27 +331,60 @@ static void handle_hangup(int) if (crawl_state.seen_hups++) return; + interrupt_activity( AI_FORCE_INTERRUPT ); + +#ifdef USE_TILE + // XXX: Will a tiles build ever need to handle the HUP signal? + sighup_save_and_exit(); +#elif defined(USE_CURSES) + // When using Curses, closing stdin will cause any Curses call blocking + // on key-presses to immediately return, including any call that was + // still blocking in the main thread when the HUP signal was caught. + // This should guarantee that the main thread will un-stall and + // will eventually return to _input() in acr.cc, which will then + // call sighup_save_and_exit(). + // + // The point to all this is that if a user is playing a game on a + // remote server and disconnects at a --more-- prompt, that when + // the player reconnects the code behind the more() call will execute + // before the disconnected game is saved, thus (for example) preventing + // the hack of avoiding excomunication consesquences because of the + // more() after "You have lost your religion!" + fclose(stdin); +#else + #error "Must use either Curses or tiles on Unix" +#endif +} + +void sighup_save_and_exit() +{ + if (crawl_state.seen_hups == 0) + { + mpr("sighup_save_and_exit() called without a HUP signal; please" + "file a bug report", MSGCH_ERROR); + return; + } + if (crawl_state.saving_game || crawl_state.updating_scores) return; crawl_state.saving_game = true; if (crawl_state.need_save) { + mpr("Received HUP signal, saved and exited game.", MSGCH_ERROR); + // Clean up all the hooks. for (unsigned i = 0; i < crawl_state.exit_hooks.size(); ++i) crawl_state.exit_hooks[i]->restore_state(); crawl_state.exit_hooks.clear(); - // save_game(true) also exits, saving us the trouble of doing so. - save_game(true); + // save_game(true) exits from the game. The "true" is also required + // to save changes to the current level. + save_game(true, "Received HUP signal, saved game."); } else - { - // CROAK! No attempt to clean up curses. This is probably not an - // issue since the term has gone away. - exit(1); - } + end(0, false, "Received HUP signal, game already saved."); } #endif // SIGHUP_SAVE @@ -807,6 +841,10 @@ void get_input_line_from_curses( char *const buff, int len ) echo(); wgetnstr( stdscr, buff, len ); noecho(); + + // Don't return a partial string if a HUP signal interrupted things. + if (crawl_state.seen_hups) + buff[0] = '\0'; } int clrscr() diff --git a/crawl-ref/source/libunix.h b/crawl-ref/source/libunix.h index 4816e43a87..8e6b2d943b 100644 --- a/crawl-ref/source/libunix.h +++ b/crawl-ref/source/libunix.h @@ -68,6 +68,10 @@ inline bool is_smart_cursor_enabled() { return (false); } void set_mouse_enabled(bool enabled); +#if defined(SIGHUP_SAVE) && defined(USE_UNIX_SIGNALS) +void sighup_save_and_exit(); +#endif + #ifndef _LIBUNIX_IMPLEMENTATION /* Some stuff from curses, to remove compiling warnings.. */ extern "C" diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc index e25830f62d..642153cc27 100644 --- a/crawl-ref/source/message.cc +++ b/crawl-ref/source/message.cc @@ -1029,7 +1029,7 @@ void reset_more_autoclear() void more(bool user_forced) { - if (crawl_state.game_crashed) + if (crawl_state.game_crashed || crawl_state.seen_hups) return; #ifdef DEBUG_DIAGNOSTICS diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index 412c11dcf6..a5860e13ae 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -6561,6 +6561,7 @@ void excommunication(god_type new_god) redraw_skill(you.your_name, player_title()); mpr("You have lost your religion!"); + more(); #ifdef DGL_MILESTONES mark_milestone("god.renounce", "abandoned " + god_name(old_god) + "."); @@ -7389,6 +7390,7 @@ void god_pitch(god_type which_god) simple_god_message( make_stringf(" welcomes you%s!", you.worshipped[which_god] ? " back" : "").c_str()); + more(); // When you start worshipping a good god, you make all non-hostile // evil and unholy beings hostile; when you start worshipping Zin, diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 6499232913..df14c46325 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -1320,6 +1320,18 @@ static bool _teleport_player( bool allow_control, bool new_abyss_area ) show_map(pos, false); redraw_screen(); +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // If we've received a HUP signal then the user can't choose a + // location, so cancel the teleport. + if (crawl_state.seen_hups) + { + mpr("Controlled teleport interrupted by HUP signal, " + "cancelling teleport.", MSGCH_ERROR); + you.turn_is_over = false; + return (false); + } +#endif + #if DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Target square (%d,%d)", pos.x, pos.y ); #endif diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index bb949801dd..b9b55300eb 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -790,7 +790,7 @@ void end(int exit_code, bool print_error, const char *format, ...) } #if defined(WIN32CONSOLE) || defined(DOS) || defined(DGL_PAUSE_AFTER_ERROR) - if (exit_code && !crawl_state.arena) + if (exit_code && !crawl_state.arena && !crawl_state.seen_hups) { fprintf(stderr, "Hit Enter to continue...\n"); getchar(); @@ -1080,12 +1080,21 @@ bool yesno( const char *str, bool safe, int safeanswer, bool clear_after, int tmp = getchm(KMC_CONFIRM); +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // Prevent infinite loop if Curses HUP signal handling happens; + // if there is no safe answer, then just save-and-exit immediately, + // since there's no way to know if it would be better to return + // true or false. + if (crawl_state.seen_hups && !safeanswer) + sighup_save_and_exit(); +#endif + if (map && map->find(tmp) != map->end()) tmp = map->find(tmp)->second; if (safeanswer && (tmp == ' ' || tmp == ESCAPE || tmp == CONTROL('G') - || tmp == '\r' || tmp == '\n')) + || tmp == '\r' || tmp == '\n' || crawl_state.seen_hups)) { tmp = safeanswer; } @@ -1181,8 +1190,11 @@ int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, int tmp = getchm(KMC_CONFIRM); - if (tmp == CK_ESCAPE || tmp == CONTROL('G') || tmp == 'q' || tmp == 'Q') + if (tmp == CK_ESCAPE || tmp == CONTROL('G') || tmp == 'q' || tmp == 'Q' + || crawl_state.seen_hups) + { return -1; + } if ((tmp == ' ' || tmp == '\r' || tmp == '\n') && safeanswer) tmp = safeanswer; diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 7b8b544c21..af2cf98c89 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -3522,6 +3522,16 @@ void show_map( coord_def &spec_place, bool travel_mode ) while (map_alive) { +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) && defined(USE_CURSES) + // If we've received a HUP signal then the user can't choose a + // location, so indicate this by returning an invalid position. + if (crawl_state.seen_hups) + { + spec_place = coord_def(-1, -1); + return; + } +#endif + start_y = screen_y - half_screen; move_x = move_y = 0; |