"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: tog atexit() infinite loop
To:
gameoftrees@openbsd.org
Date:
Fri, 20 May 2022 10:26:08 +0200

Download raw body.

Thread
On Fri, May 20, 2022 at 10:13:14AM +0200, Stefan Sperling wrote:
> On Fri, May 20, 2022 at 10:03:34AM +0200, Stefan Sperling wrote:
> > #3  0x00000cd17cf3b5d7 in cleanup (sig=<optimized out>) at /usr/src/lib/libcurses/tty/lib_tstp.c:283
> 
> Reading the code in ncurses above, it looks like the root of the problem
> is in ncurses.
> 
> Of course, the log thread isn't supposed to be calling into curses
> at all, yet still ends up here... sigh...

For now, the best idea I have is the following. OK?

-----------------------------------------------
commit d3ce8022aa10758c9e2d856b3e52501405b06d67 (tog-signals)
from: Stefan Sperling <stsp@stsp.name>
date: Fri May 20 08:23:50 2022 UTC
 
 tog: override SIGTERM and SIGINT handlers to avoid ncurses cleanup() handler
 
diff 3d5026743b4462677a70d5a09bf4e5b65caee742 f05d359ae19407de65c59cad943debd2188f71a8
blob - a4221a9f756b84c1412ef1f4983cccd6aa233c2d
blob + 0b71fb34c2bb552a0ccbb6848d023911e8d34c72
--- tog/tog.c
+++ tog/tog.c
@@ -595,6 +595,8 @@ static const struct got_error *search_next_ref_view(st
 static volatile sig_atomic_t tog_sigwinch_received;
 static volatile sig_atomic_t tog_sigpipe_received;
 static volatile sig_atomic_t tog_sigcont_received;
+static volatile sig_atomic_t tog_sigint_received;
+static volatile sig_atomic_t tog_sigterm_received;
 
 static void
 tog_sigwinch(int signo)
@@ -614,6 +616,26 @@ tog_sigcont(int signo)
 	tog_sigcont_received = 1;
 }
 
+static void
+tog_sigint(int signo)
+{
+	tog_sigint_received = 1;
+}
+
+static void
+tog_sigterm(int signo)
+{
+	tog_sigterm_received = 1;
+}
+
+static int
+tog_fatal_signal_received()
+{
+	return (tog_sigpipe_received ||
+	    tog_sigint_received || tog_sigint_received);
+}
+
+
 static const struct got_error *
 view_close(struct tog_view *view)
 {
@@ -1040,7 +1062,7 @@ view_loop(struct tog_view *view)
 		return err;
 	update_panels();
 	doupdate();
-	while (!TAILQ_EMPTY(&views) && !done && !tog_sigpipe_received) {
+	while (!TAILQ_EMPTY(&views) && !done && !tog_fatal_signal_received()) {
 		/* Refresh fast during initialization, then become slower. */
 		if (fast_refresh && fast_refresh-- == 0)
 			halfdelay(10); /* switch to once per second */
@@ -2021,11 +2043,15 @@ block_signals_used_by_main_thread(void)
 	if (sigemptyset(&sigset) == -1)
 		return got_error_from_errno("sigemptyset");
 
-	/* tog handles SIGWINCH and SIGCONT */
+	/* tog handles SIGWINCH, SIGCONT, SIGINT, SIGTERM */
 	if (sigaddset(&sigset, SIGWINCH) == -1)
 		return got_error_from_errno("sigaddset");
 	if (sigaddset(&sigset, SIGCONT) == -1)
 		return got_error_from_errno("sigaddset");
+	if (sigaddset(&sigset, SIGINT) == -1)
+		return got_error_from_errno("sigaddset");
+	if (sigaddset(&sigset, SIGTERM) == -1)
+		return got_error_from_errno("sigaddset");
 
 	/* ncurses handles SIGTSTP */
 	if (sigaddset(&sigset, SIGTSTP) == -1)
@@ -2050,7 +2076,7 @@ log_thread(void *arg)
 	if (err)
 		return (void *)err;
 
-	while (!done && !err && !tog_sigpipe_received) {
+	while (!done && !err && !tog_fatal_signal_received()) {
 		err = queue_commits(a);
 		if (err) {
 			if (err->code != GOT_ERR_ITER_COMPLETED)
@@ -2694,6 +2720,17 @@ apply_unveil(const char *repo_path, const char *worktr
 static void
 init_curses(void)
 {
+	/*
+	 * Override default signal handlers before starting ncurses.
+	 * This should prevent ncurses from installing its own
+	 * broken cleanup() signal handler.
+	 */
+	signal(SIGWINCH, tog_sigwinch);
+	signal(SIGPIPE, tog_sigpipe);
+	signal(SIGCONT, tog_sigcont);
+	signal(SIGINT, tog_sigint);
+	signal(SIGTERM, tog_sigterm);
+
 	initscr();
 	cbreak();
 	halfdelay(1); /* Do fast refresh while initial view is loading. */
@@ -2706,9 +2743,6 @@ init_curses(void)
 		start_color();
 		use_default_colors();
 	}
-	signal(SIGWINCH, tog_sigwinch);
-	signal(SIGPIPE, tog_sigpipe);
-	signal(SIGCONT, tog_sigcont);
 }
 
 static const struct got_error *