]> granicus.if.org Git - nethack/commitdiff
hangup revamp (trunk only)
authornethack.rankin <nethack.rankin>
Tue, 16 Jan 2007 04:53:20 +0000 (04:53 +0000)
committernethack.rankin <nethack.rankin>
Tue, 16 Jan 2007 04:53:20 +0000 (04:53 +0000)
     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

index 9d5588e7313c617db72e3ede0a10cb9cbe4c0122..a694f0b692238dbd40ab94383c407c5c87cb597c 100644 (file)
--- 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 */
+#endif /* NR_OF_EOFS */
+
        if (sym == EOF) {
-# ifndef SAFERHANGUP
-           end_of_input();
-# else
-           program_state.done_hup++;
+#ifdef HANGUPHANDLING
+           hangup(0); /* call end_of_input() or set program_state.done_hup */
+#endif
            sym = '\033';
-# endif
-       }
-#endif /* UNIX */
-
-       if(sym == 0) {
+       } else if (sym == 0) {
            /* click event */
            readchar_queue = click_to_cmd(x, y, mod);
            sym = *readchar_queue++;