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

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: Bug: tog suspend/continue
To:
Christian Weisgerber <naddy@mips.inka.de>
Cc:
gameoftrees@openbsd.org
Date:
Tue, 14 Jan 2020 17:24:16 +0100

Download raw body.

Thread
On Tue, Jan 14, 2020 at 04:19:26PM +0100, Christian Weisgerber wrote:
> Stefan Sperling:
> 
> > > I bet this is related to how signals get delivered to threads.
> > > Does anyone here have some expertise in this area?
> > 
> > This seems to help?
> 
> Not a whole lot.
> 
> $ tog log -r src.git
> ^Z
> $ fg
> ^Z		# ignored
> q		# ignored
> 
> 
> $ tog blame -r src.git Makefile
> ^Z
> $ fg
> <any input>	# ignored

Some debugging with bluhm revealed that ncurses uses SIGTSTP and this
signal should only be handled by the main thread.

Is this better?

diff f13374f454ced0d17abbf1d7a4586ccc242ea652 /home/stsp/src/got
blob - 1532cdc54cedb2f4cc0259d27ef65a8dce22f014
file + tog/tog.c
--- tog/tog.c
+++ tog/tog.c
@@ -24,6 +24,7 @@
 #undef _XOPEN_SOURCE_EXTENDED
 #include <panel.h>
 #include <locale.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <getopt.h>
@@ -470,6 +471,7 @@ static const struct got_error *search_next_tree_view(s
 
 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 void
 tog_sigwinch(int signo)
@@ -483,6 +485,12 @@ tog_sigpipe(int signo)
 	tog_sigpipe_received = 1;
 }
 
+static void
+tog_sigcont(int signo)
+{
+	tog_sigcont_received = 1;
+}
+
 static const struct got_error *
 view_close(struct tog_view *view)
 {
@@ -763,9 +771,10 @@ view_input(struct tog_view **new, struct tog_view **de
 		return got_error_set_errno(errcode, "pthread_mutex_lock");
 	nodelay(stdscr, TRUE);
 
-	if (tog_sigwinch_received) {
+	if (tog_sigwinch_received || tog_sigcont_received) {
 		tog_resizeterm();
 		tog_sigwinch_received = 0;
+		tog_sigcont_received = 0;
 		TAILQ_FOREACH(v, views, entry) {
 			err = view_resize(v);
 			if (err)
@@ -1871,6 +1880,32 @@ browse_commit_tree(struct tog_view **new_view, int beg
 	return err;
 }
 
+static const struct got_error *
+block_signals_used_by_main_thread(void)
+{
+	sigset_t sigset;
+	int errcode;
+
+	if (sigemptyset(&sigset) == -1)
+		return got_error_from_errno("sigemptyset");
+
+	/* tog handles SIGWINCH and SIGCONT */
+	if (sigaddset(&sigset, SIGWINCH) == -1)
+		return got_error_from_errno("sigaddset");
+	if (sigaddset(&sigset, SIGCONT) == -1)
+		return got_error_from_errno("sigaddset");
+
+	/* ncurses handles SIGTSTP */
+	if (sigaddset(&sigset, SIGTSTP) == -1)
+		return got_error_from_errno("sigaddset");
+
+	errcode = pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+	if (errcode)
+		return got_error_set_errno(errcode, "pthread_sigmask");
+
+	return NULL;
+}
+
 static void *
 log_thread(void *arg)
 {
@@ -1879,6 +1914,10 @@ log_thread(void *arg)
 	struct tog_log_thread_args *a = arg;
 	int done = 0;
 
+	err = block_signals_used_by_main_thread();
+	if (err)
+		return (void *)err;
+
 	while (!done && !err && !tog_sigpipe_received) {
 		err = queue_commits(a->graph, a->commits, 1, a->repo,
 		    a->in_repo_path, a->searching, a->search_next_done,
@@ -2453,6 +2492,7 @@ init_curses(void)
 	}
 	signal(SIGWINCH, tog_sigwinch);
 	signal(SIGPIPE, tog_sigpipe);
+	signal(SIGCONT, tog_sigcont);
 }
 
 static const struct got_error *
@@ -3522,6 +3562,10 @@ blame_thread(void *arg)
 	struct tog_blame_thread_args *ta = arg;
 	struct tog_blame_cb_args *a = ta->cb_args;
 	int errcode;
+
+	err = block_signals_used_by_main_thread();
+	if (err)
+		return (void *)err;
 
 	err = got_blame(ta->path, a->commit_id, ta->repo,
 	    blame_cb, ta->cb_args, ta->cancel_cb, ta->cancel_arg);