at the more after "You have lost your religion!" to avoid the negative consequences of excommunication): when a HUP signal is received, instead of immediately saving the game, close the stdin stream, which will cause all of the Curses calls which normal block on key-presses to unblock, so that the code after a more() call will execute before the disconnected game is saved (which will happen in _input() in acr.cc). This only affects Curses (non-tiles/console) UNIX builds which have both USE_UNIX_SIGNALS and SIGHUP_SAVE defined.
Exceptions to the above:
If HUP is received during a call to yesno() with safeanswer == 0, then the game will be saved immediately, since there's no way for the function to tell which answer is safe to give automatically.
If HUP is received while selecting the target for a controlled teleport then the teleport will be canceled, since otherwise a target other than the intended one might be the one under the cursor when the disconnect happened.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10443 c06c8d41-db1a-0410-9941-cceddc491573
C7WZ2EB2RK7JH5UG34EHFFOLHG5UVJU7BDRJ5J5GCB2ZRIVQGLGAC
UR4ND452TYBKRQ4W2CY6VXHOFSWU2Y4MVRNEMFM4LKLA6S7OBYHQC
AB54PPWAC5KCCSZI7FXV5QEOJNEIGAMCN4XZVPWR2P77AVAN7FOQC
RQ24Y25QDO2GY65XESEVBCP6VXCB7BDTWXO42IPPI6UPRJQ5XYDAC
ZXMXDBYYGS2YYAFUZFWBZ5VT2HQ2NRZIC4HJJLWZYXRJ2ZSGN36QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
AJJ6D6JRV6ZAZOAUHYUM2IQG42V6PBALOD4KEMNKSVVAOJXAUCPQC
KLJIFEBICFQ76DNM3MTS2PJ5LTEIOBIW5QZTNW722WHPKIST5UQQC
PKXXBHS3LWLPZI2QVRX22MSQ4R2626IXRSNHFFYHXYTLJJQU54LQC
4Q5OYUKF2SGF7WHMIVYFZVXXDCFUCYY534VLOGKWYRSPYKRXMVDAC
JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
QTGDLSVMXXROGGKE7JRHRJ7GQIQM3CAB2ETBB4FW6WRDR7VCFO3QC
IYDUDWPDA7JST3MVKYBAAX7GYDSM6FXXQ2QMMIKEDQLT4VXTHOUAC
2OPTG7FWHLKQYXJIL4BDN3UW67CV3SKILQE6NTOA3YBYI5V7SQSQC
IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC
UXBKTJSK6DEFSCQ4HB36YM6KVFGWYVCEORXIMOKQ3JZL4NNEOKGQC
YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC
QX7GM3YZFUBCXTLQIKF27YOPKYR2655HYRWSNTDXXI6CTH4XEP7AC
CCRQESB4ADT4WA7FGLNZZXAJ6G5QMCTYCZIWORBN45P6ZPILC34AC
BSI5DB3LVY42ZHOS46X2CAPPVOSOTTQWFGLTMAKRFTROI5BQWFDQC
HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC
SPOCLROO64OKT2F6SGUJNAQXH2XZWCK3LE7IRCDQCRYPU6Q6SAFQC
TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC
MVQRUYIXCXGGH7J7TN2GKUQL23EOBLYGPJL4TBQKCZR2D6DCL7XQC
ANOEQTM6IGCBTESKKQ5PCBSDTZ7VGRCMDIOAFEH4R7DJHKWKDFAAC
IH5TVAZGKN7IQOTSOJ56WG5C3CMTG3AI63XT3XVNHC7DI4N2TSUAC
NEECVIIAOBP72T6O44DWAA6HFSDY3KSWYCFMKAEMDMVOI7XASD7QC
GBUB77EAYHOFY6GQ5IY3ZSBC7FSQFZZKYNBD5QMCQFIKFLYLWHOQC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
#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 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
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);
// 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.");
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;
#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
#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