]> granicus.if.org Git - nethack/commitdiff
signal induced panictrace under curses
authorPatR <rankin@nethack.org>
Tue, 9 Mar 2021 15:45:58 +0000 (07:45 -0800)
committerPatR <rankin@nethack.org>
Tue, 9 Mar 2021 15:45:58 +0000 (07:45 -0800)
When panictrace feedback occurs due to catching a signal rather
than controlled panic, the backtrace is useless when running the
curses interface unless the terminal gets reset first.  Let's
just hope that the signal triggering a panictrace doesn't occur
while resetting the terminal.

doc/fixes37.0
include/wincurs.h
src/end.c
win/curses/cursmain.c

index 9e7afcbd04ad35769aa4ab1d2e9ebfc29983a4f6..650b4a4440f02ce64b602b38fef729b449a79689 100644 (file)
@@ -1,4 +1,4 @@
-NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.468 $ $NHDT-Date: 1615158479 2021/03/07 23:07:59 $
+NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.469 $ $NHDT-Date: 1615304752 2021/03/09 15:45:52 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -828,6 +828,7 @@ curses: implement 'selectsaved', restore via menu of saved games
 curses: implement selecting menu items via mouse
 curses: 'windowborders' can be set to 3 or 4 to suppress perm_invent borders
        to provide slightly more room for actual inventory info
+curses: if panictrace is triggered, reset the terminal before giving backtrace
 Qt: the "paper doll" inventory subset can be controlled via the "Qt Settings"
        dialog box ("Preferences..." on OSX)
 Qt: draw a border around each tile in the paper doll inventory; when BUC is
index 38567e8237589d95f2f3c584210c56c431e79c99..5cd8502a12006f9d52dbabaf62d673f6ec663896 100644 (file)
@@ -69,6 +69,7 @@ extern void curses_init_nhwindows(int* argcp, char** argv);
 extern void curses_player_selection(void);
 extern void curses_askname(void);
 extern void curses_get_nh_event(void);
+extern void curses_uncurse_terminal(void);
 extern void curses_exit_nhwindows(const char *str);
 extern void curses_suspend_nhwindows(const char *str);
 extern void curses_resume_nhwindows(void);
index 395ea450c442b40dc56a43b93d5f019977b8ab85..288e95e504d952530a8091cd8707b5768af94f98 100644 (file)
--- a/src/end.c
+++ b/src/end.c
@@ -1,4 +1,4 @@
-/* NetHack 3.7 end.c   $NHDT-Date: 1612316744 2021/02/03 01:45:44 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.220 $ */
+/* NetHack 3.7 end.c   $NHDT-Date: 1615304753 2021/03/09 15:45:53 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.222 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -109,6 +109,20 @@ panictrace_handler(int sig_unused UNUSED)
 {
 #define SIG_MSG "\nSignal received.\n"
     int f2;
+
+#ifdef CURSES_GRAPHICS
+    if (iflags.window_inited && WINDOWPORT("curses")) {
+        extern void curses_uncurse_terminal(void); /* wincurs.h */
+
+        /* it is risky calling this during a program-terminating signal,
+           but without it the subsequent backtrace is useless because
+           that ends up being scrawled all over the screen; call is
+           here rather than in NH_abort() because panic() calls both
+           exit_nhwindows(), which makes this same call under curses,
+           then NH_abort() and we don't want to call this twice */
+        curses_uncurse_terminal();
+    }
+#endif
     
     f2 = (int) write(2, SIG_MSG, sizeof SIG_MSG - 1);
     nhUse(f2);  /* what could we do if write to fd#2 (stderr) fails  */
@@ -156,8 +170,10 @@ NH_abort(void)
 {
     int gdb_prio = SYSOPT_PANICTRACE_GDB;
     int libc_prio = SYSOPT_PANICTRACE_LIBC;
-    static boolean aborting = FALSE;
+    static volatile boolean aborting = FALSE;
 
+    /* don't execute this code recursively if a second abort is requested
+       while this routine or the code it calls is executing */
     if (aborting)
         return;
     aborting = TRUE;
@@ -553,8 +569,8 @@ fixup_death(int how)
 DISABLE_WARNING_FORMAT_NONLITERAL
 
 /*VARARGS1*/
-void panic
-VA_DECL(const char *, str)
+void
+panic VA_DECL(const char *, str)
 {
     VA_START(str);
     VA_INIT(str, char *);
index 5024bddd58bb11edda0f1dd469ca2f7d5d4f3e4e..e22b770f55530a2b2c9099bc208dbecae5ab092a 100644 (file)
@@ -299,6 +299,19 @@ curses_get_nh_event(void)
     }
 }
 
+/* restore terminal state; extracted from curses_exit_nhwindows() */
+void
+curses_uncurse_terminal(void)
+{
+   /* also called by panictrace_handler(), a signal handler, so somewhat
+      iffy in that situation; but without this, newlines behave as raw
+      line feeds so subseqent backtrace gets scrawled all over the screen
+      and is nearly useless */
+    curses_cleanup();
+    curs_set(orig_cursor);
+    endwin();
+}
+
 /* Exits the window system.  This should dismiss all windows,
    except the "window" used for raw_print().  str is printed if possible.
 */
@@ -311,9 +324,8 @@ curses_exit_nhwindows(const char *str)
     curses_destroy_nhwindow(MESSAGE_WIN);
     curs_destroy_all_wins();
 
-    curses_cleanup();
-    curs_set(orig_cursor);
-    endwin();
+    curses_uncurse_terminal();
+
     iflags.window_inited = 0;
     if (str != NULL) {
         raw_print(str);