From c224298787a61857f6dabe87cdd7cda3be243ec2 Mon Sep 17 00:00:00 2001 From: dshaligram Date: Tue, 19 Dec 2006 13:24:40 +0000 Subject: SIGHUP handling for 0.1.6. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.1.6@674 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/AppHdr.h | 4 ++++ crawl-ref/source/acr.cc | 10 +++++++--- crawl-ref/source/externs.h | 15 +++++++++++++++ crawl-ref/source/files.cc | 9 +++++++++ crawl-ref/source/files.h | 2 ++ crawl-ref/source/hiscores.cc | 10 ++++++++-- crawl-ref/source/libunix.cc | 39 +++++++++++++++++++++++++++++++++++---- crawl-ref/source/libutil.h | 17 +++++++++++++++++ crawl-ref/source/misc.cc | 4 ++-- crawl-ref/source/ouch.cc | 17 ++++++++++++----- 10 files changed, 111 insertions(+), 16 deletions(-) diff --git a/crawl-ref/source/AppHdr.h b/crawl-ref/source/AppHdr.h index 138915ea2e..5b62182a8c 100644 --- a/crawl-ref/source/AppHdr.h +++ b/crawl-ref/source/AppHdr.h @@ -95,6 +95,10 @@ #define MULTIUSER #define USE_UNIX_SIGNALS + // If this is defined, Crawl will attempt to save and exit when it + // receives a hangup signal. + #define SIGHUP_SAVE + #define FILE_SEPARATOR '/' #define CHARACTER_SET 0 diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index 134ef99b35..b71211e8f9 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -124,9 +124,10 @@ #include "view.h" #include "stash.h" -struct crawl_environment env; -struct player you; -struct system_environment SysEnv; +crawl_environment env; +player you; +system_environment SysEnv; +game_state crawl_state; std::string init_file_location; // externed in newgame.cc @@ -2827,6 +2828,9 @@ static bool initialise(void) viewwindow(1, false); // This just puts the view up for the first turn. activate_notes(true); + + crawl_state.need_save = true; + return (ret); } diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index dff17a277c..74c51e51aa 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -640,6 +640,21 @@ struct crawl_environment extern struct crawl_environment env; +// Track stuff for SIGHUP handling. +struct game_state +{ + bool need_save; // Set to true when game has started. + bool saving_game; // Set to true while in save_game. + bool updating_scores; // Set to true while updating hiscores. + + int seen_hups; // Set to true if SIGHUP received. + + game_state() : need_save(false), saving_game(false), + updating_scores(false), seen_hups(0) + { + } +}; +extern game_state crawl_state; struct ghost_struct { diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc index 241a367fb3..cecc2b96aa 100644 --- a/crawl-ref/source/files.cc +++ b/crawl-ref/source/files.cc @@ -1177,6 +1177,7 @@ void save_level(int level_saved, bool was_a_labyrinth, char where_were_you) void save_game(bool leave_game) { + unwind_bool saving_game(crawl_state.saving_game, true); #ifdef STASH_TRACKING /* Stashes */ @@ -1276,6 +1277,14 @@ void save_game(bool leave_game) end(0); } // end save_game() +// Saves the game without exiting. +void save_game_state() +{ + save_game(false); + if (crawl_state.seen_hups) + save_game(true); +} + void load_ghost(void) { char majorVersion; diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h index 93a837b659..ecc900494c 100644 --- a/crawl-ref/source/files.h +++ b/crawl-ref/source/files.h @@ -52,6 +52,8 @@ void load( unsigned char stair_taken, int load_mode, bool was_a_labyrinth, * *********************************************************************** */ void save_game(bool leave_game); +// Save game without exiting (used when changing levels). +void save_game_state(); // last updated 12may2000 {dlb} /* *********************************************************************** diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index c0ccd75e43..27031e7337 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -105,6 +105,8 @@ std::string log_file_name() void hiscores_new_entry( const scorefile_entry &ne ) { + unwind_bool score_update(crawl_state.updating_scores, true); + FILE *scores; int i, total_entries; bool inserted = false; @@ -175,6 +177,8 @@ void hiscores_new_entry( const scorefile_entry &ne ) void logfile_new_entry( const scorefile_entry &ne ) { + unwind_bool logfile_update(crawl_state.updating_scores, true); + FILE *logfile; scorefile_entry le = ne; @@ -225,6 +229,8 @@ static void hiscores_print_entry(const scorefile_entry &se, // Writes all entries in the scorefile to stdout in human-readable form. void hiscores_print_all(int display_count, int format) { + unwind_bool scorefile_display(crawl_state.updating_scores, true); + FILE *scores = hs_open("r", score_file_name()); if (scores == NULL) { @@ -249,6 +255,8 @@ void hiscores_print_all(int display_count, int format) // hiscores_print_all. void hiscores_print_list( int display_count, int format ) { + unwind_bool scorefile_display(crawl_state.updating_scores, true); + FILE *scores; int i, total_entries; @@ -437,8 +445,6 @@ static bool unlock_file_handle( FILE *handle ) #endif - - FILE *hs_open( const char *mode, const std::string &scores ) { // allow reading from standard input diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index 3aee4c0981..5affa16940 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -45,6 +45,7 @@ #include "enum.h" #include "externs.h" +#include "files.h" #include @@ -198,6 +199,35 @@ int getch_ck() { } } +#if defined(USE_UNIX_SIGNALS) && defined(SIGHUP_SAVE) + +/* [ds] This SIGHUP handling is primitive and far from safe, but it + * should be better than nothing. Feel free to get rigorous on this. + */ +static void handle_hangup(int) +{ + if (crawl_state.seen_hups++) + return; + + if (crawl_state.saving_game || crawl_state.updating_scores) + return; + + crawl_state.saving_game = true; + if (crawl_state.need_save) + { + // save_game(true) also exits, saving us the trouble of doing so. + save_game(true); + } + else + { + // CROAK! No attempt to clean up curses. This is probably not an + // issue since the term has gone away. + exit(1); + } +} + +#endif // USE_UNIX_SIGNALS && SIGHUP_SAVE + void unixcurses_startup( void ) { termio_init(); @@ -209,13 +239,15 @@ void unixcurses_startup( void ) #ifdef SIGINT signal(SIGINT, SIG_IGN); -#endif #endif - //savetty(); +#ifdef SIGHUP_SAVE + signal(SIGHUP, handle_hangup); +#endif + +#endif initscr(); - // cbreak(); raw(); noecho(); @@ -228,7 +260,6 @@ void unixcurses_startup( void ) ESCDELAY = CURSES_SET_ESCDELAY; #endif #endif - //cbreak(); meta(stdscr, TRUE); start_color(); diff --git a/crawl-ref/source/libutil.h b/crawl-ref/source/libutil.h index 6b31b93728..0f232baa72 100644 --- a/crawl-ref/source/libutil.h +++ b/crawl-ref/source/libutil.h @@ -125,6 +125,23 @@ enum KEYS CK_CTRL_PGDN }; +// Sets a boolean to a new value in the scope of the object instance. +class unwind_bool +{ +public: + unwind_bool(bool &val_, bool newval) : val(val_), oldval(val_) + { + val = newval; + } + ~unwind_bool() + { + val = oldval; + } +private: + bool &val; + bool oldval; +}; + class cursor_control { public: diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index f08840d5bf..33be41d5df 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -634,7 +634,7 @@ void up_stairs(void) you.turn_is_over = true; - save_game(false); + save_game_state(); new_level(); @@ -1073,7 +1073,7 @@ void down_stairs( bool remove_stairs, int old_level, bool force ) you.turn_is_over = true; - save_game(false); + save_game_state(); new_level(); diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index 1ee91d02b3..a4e0360e24 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -776,6 +776,9 @@ void ouch( int dam, int death_source, char death_type, const char *aux ) //okay, so you're dead: + crawl_state.need_save = false; + crawl_state.updating_scores = true; + // prevent bogus notes activate_notes(false); @@ -870,8 +873,8 @@ void end_game( struct scorefile_entry &se ) const int num_suffixes = sizeof(suffixes) / sizeof(const char*); for ( i = 0; i < num_suffixes; ++i ) { - std::string tmpname = basename + suffixes[i]; - unlink( tmpname.c_str() ); + std::string tmpname = basename + suffixes[i]; + unlink( tmpname.c_str() ); } // death message @@ -880,7 +883,9 @@ void end_game( struct scorefile_entry &se ) mpr("You die..."); // insert player name here? {dlb} viewwindow(1, false); // don't do this for leaving/winning characters } - more(); + + if (!crawl_state.seen_hups) + more(); for (i = 0; i < ENDOFPACK; i++) set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK ); @@ -900,7 +905,8 @@ void end_game( struct scorefile_entry &se ) if (!dump_char( morgue_name(), !dead, true )) { mpr("Char dump unsuccessful! Sorry about that."); - more(); + if (!crawl_state.seen_hups) + more(); clrscr(); } @@ -925,6 +931,7 @@ void end_game( struct scorefile_entry &se ) hiscores_print_list( get_number_of_lines() - lines - 5 ); // just to pause, actual value returned does not matter {dlb} - get_ch(); + if (!crawl_state.seen_hups) + get_ch(); end(0); } -- cgit v1.2.3-54-g00ecf