From: PatR Date: Tue, 9 Mar 2021 15:45:58 +0000 (-0800) Subject: signal induced panictrace under curses X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc855d697364e2abbd07247b91b33d3c79099269;p=nethack signal induced panictrace under curses 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. --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 9e7afcbd0..650b4a444 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/wincurs.h b/include/wincurs.h index 38567e823..5cd8502a1 100644 --- a/include/wincurs.h +++ b/include/wincurs.h @@ -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); diff --git a/src/end.c b/src/end.c index 395ea450c..288e95e50 100644 --- 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 *); diff --git a/win/curses/cursmain.c b/win/curses/cursmain.c index 5024bddd5..e22b770f5 100644 --- a/win/curses/cursmain.c +++ b/win/curses/cursmain.c @@ -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);