summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc11
-rw-r--r--crawl-ref/source/cio.cc9
-rw-r--r--crawl-ref/source/directn.cc26
-rw-r--r--crawl-ref/source/effects.cc13
-rw-r--r--crawl-ref/source/libunix.cc52
-rw-r--r--crawl-ref/source/libunix.h4
-rw-r--r--crawl-ref/source/message.cc2
-rw-r--r--crawl-ref/source/spells3.cc12
-rw-r--r--crawl-ref/source/stuff.cc18
-rw-r--r--crawl-ref/source/view.cc10
10 files changed, 145 insertions, 12 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 9318b863ee..58acce1cdd 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -878,6 +878,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();
@@ -1022,6 +1027,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
@@ -2497,6 +2507,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 b9ff80c25f..b3382bf6fc 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 9fd43d7dbc..333d733e54 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)
{
@@ -1069,6 +1082,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 21ea6807d4..b7898e8d47 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -1572,7 +1572,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 e5606cd39c..67e4739f02 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -1023,7 +1023,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/spells3.cc b/crawl-ref/source/spells3.cc
index 8740fae83d..56d2c079aa 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -1319,6 +1319,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 43bcdb7a77..da82087544 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -775,7 +775,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();
@@ -1065,12 +1065,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;
}
@@ -1166,8 +1175,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 69be6e93d3..7d4878c93f 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -3475,6 +3475,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;