From b01f1f804fbeb80bb370f2535e0267e65fd8beeb Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Tue, 16 Jan 2007 04:53:20 +0000 Subject: [PATCH] hangup revamp (trunk only) The previous "hangup cleanup" didn't accomplish much (other than to give everyone a good view of extern.h). This one achieves more, and also tries to fix the bug From a bug report: > Buglet: Destroy old game -prompt can make game unrecoverable > > I haven't confirmed this myself, but few people playing on NAO > have had the following happen: > 1) play nethack > 2) your network connection gets cut > 3) reconnect, and get "Destroy old game" -prompt > 4) your network connection gets cut, again, before you get to answer 'n' > 5) game is not recoverable, because the level 0 file is gone. The reason for #5 is simple to explain; it's the expected behavior of current hangup() routine (although that hasn't always called clearlocks(); I don't know why it was added). The puzzle is why #2 left any lock files around in the first place. I suspect it was because SAFERHANGUP defers until rhack(), and rhack() doesn't get called if the hero is immobilized or in the midst of a counted operation. I don't know how long a disconnected process is allowed to run, but I don't think it's forever. (Alternatively, nethack might be attempting further terminal I/O and getting stuck on the hung connection; this won't help much if that's the case.) This turns clearlocks() into a no-op during the period when the UNIX port is asking the user to confirm whether to overwrite an existing game. Also, this removes the duplication of code and function between hangup() and end_of_input(), and it simplifies the check for whether hangups are supported by adding new macro HANGUPHANDLING. (I don't think global.h is the best place to be defining that but I couldn't figure out where else it would fit, other than repeating for individual xxxconf.h files.) And adds a couple more done_hup checks to try to cope with situations where rhack() is being bypassed. Lastly, having readchar() return EOF was ignored for non-UNIX configs; now everybody gets ESC instead of letting EOF be seen further inside the core. --- src/cmd.c | 60 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/cmd.c b/src/cmd.c index 9d5588e73..a694f0b69 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)cmd.c 3.5 2006/07/08 */ +/* SCCS Id: @(#)cmd.c 3.5 2007/01/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,7 @@ struct cmd Cmd = { 0 }; /* flag.h */ +#ifdef UNIX /* * Some systems may have getchar() return EOF for various reasons, and * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. @@ -15,6 +16,7 @@ struct cmd Cmd = { 0 }; /* flag.h */ #if defined(SYSV) || defined(DGUX) || defined(HPUX) #define NR_OF_EOFS 20 #endif +#endif #define CMD_TRAVEL (char)0x90 #define CMD_CLICKLOOK (char)0x8F @@ -159,9 +161,6 @@ STATIC_PTR boolean NDECL(minimal_enlightenment); STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *,char *)); STATIC_DCL char *FDECL(enlght_combatinc, (const char *,int,int,char *)); -#if defined(UNIX) || defined(SAFERHANGUP) -static void NDECL(end_of_input); -#endif static const char* readchar_queue=""; static coord clicklook_cc; @@ -2798,22 +2797,42 @@ parse() return(in_line); } -#if defined(UNIX) || defined(SAFERHANGUP) -static +#ifdef HANGUPHANDLING +/*ARGUSED*/ +void +hangup(sig_unused) /* called as signal() handler, so sent at least one arg */ +int sig_unused; +{ +# ifdef SAFERHANGUP + /* When using SAFERHANGUP, the done_hup flag it tested in rhack + and a couple of other places; actual hangup handling occurs then. + This is 'safer' because it disallows certain cheats and also + protects against losing objects in the process of being thrown, + but also potentially riskier because the disconnected program + must continue running longer before attempting a hangup save. */ + program_state.done_hup++; +# else + end_of_input(); +# endif /* ?SAFERHANGUP */ +} + void end_of_input() { -#ifndef NOSAVEONHANGUP +# ifdef NOSAVEONHANGUP + program_state_something_worth_saving = 0; +# endif # ifndef SAFERHANGUP if (!program_state.done_hup++) -#endif +# endif if (program_state.something_worth_saving) (void) dosave0(); -#endif exit_nhwindows((char *)0); clearlocks(); terminate(EXIT_SUCCESS); + /*NOTREACHED*/ /* not necessarily true for vms... */ + return; } -#endif +#endif /* HANGUPHANDLING */ char readchar() @@ -2830,8 +2849,7 @@ readchar() sym = Getchar(); #endif -#ifdef UNIX -# ifdef NR_OF_EOFS +#ifdef NR_OF_EOFS if (sym == EOF) { register int cnt = NR_OF_EOFS; /* @@ -2844,18 +2862,14 @@ readchar() sym = Getchar(); } while (--cnt && sym == EOF); } -# endif /* NR_OF_EOFS */ - if (sym == EOF) { -# ifndef SAFERHANGUP - end_of_input(); -# else - program_state.done_hup++; - sym = '\033'; -# endif - } -#endif /* UNIX */ +#endif /* NR_OF_EOFS */ - if(sym == 0) { + if (sym == EOF) { +#ifdef HANGUPHANDLING + hangup(0); /* call end_of_input() or set program_state.done_hup */ +#endif + sym = '\033'; + } else if (sym == 0) { /* click event */ readchar_queue = click_to_cmd(x, y, mod); sym = *readchar_queue++;