fix suspending and resuming tog with Ctrl-Z and fg; issue reported by naddy@
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
diff --git a/tog/tog.c b/tog/tog.c
index 1532cdc..cb39099 100644
--- a/tog/tog.c
+++ b/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(struct tog_view *);
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 **dead,
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 begin_x,
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 *
@@ -3523,6 +3563,10 @@ blame_thread(void *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);
if (err && err->code == GOT_ERR_CANCELLED)