From 71e8361184fb19845e65fdd06538948a5376ccbf Mon Sep 17 00:00:00 2001 From: Roland Walker Date: Mon, 21 May 2018 14:11:53 -0400 Subject: [PATCH 1/2] make tig the process-group leader and give it the foreground connection to the TTY. This announces to the OS "I am an interactive program taking input". In the most common case, this will already have been arranged by the user's shell. This init is logically done as early as possible, as child processes inherit these characteristics. This also allows tig to easily ensure child process cleanup at exit. --- include/tig/display.h | 1 + src/display.c | 11 +++++++++-- src/tig.c | 2 ++ test/README.adoc | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/tig/display.h b/include/tig/display.h index b44579868..b76dd19b8 100644 --- a/include/tig/display.h +++ b/include/tig/display.h @@ -43,6 +43,7 @@ extern unsigned int current_view; #define view_is_displayed(view) \ (view == display[0] || view == display[1]) +void init_tty(void); void init_display(void); void resize_display(void); void redraw_display(bool clear); diff --git a/src/display.c b/src/display.c index 265a3a056..5d706bf1d 100644 --- a/src/display.c +++ b/src/display.c @@ -584,7 +584,7 @@ set_terminal_modes(void) leaveok(stdscr, false); } -static void +void init_tty(void) { /* open */ @@ -598,6 +598,12 @@ init_tty(void) if (!opt_tty.attr) die("Failed allocation for tty attributes"); tcgetattr(opt_tty.fd, opt_tty.attr); + + /* process-group leader */ + signal(SIGTTOU, SIG_IGN); + setpgid(getpid(), getpid()); + tcsetpgrp(opt_tty.fd, getpid()); + signal(SIGTTOU, SIG_DFL); } void @@ -607,7 +613,8 @@ init_display(void) const char *term; int x, y; - init_tty(); + if (!opt_tty.file) + die("Can't initialize display without tty"); die_callback = done_display; if (atexit(done_display)) diff --git a/src/tig.c b/src/tig.c index d3c1da8e6..7b9e417b8 100644 --- a/src/tig.c +++ b/src/tig.c @@ -772,6 +772,8 @@ main(int argc, const char *argv[]) enum request request = parse_options(argc, argv, pager_mode); struct view *view; + init_tty(); + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) die("Failed to setup signal handler"); diff --git a/test/README.adoc b/test/README.adoc index 40bdbcc17..6aa8e8dab 100644 --- a/test/README.adoc +++ b/test/README.adoc @@ -11,6 +11,9 @@ test scripts as long as `PATH` is set to include the directories `src/` and `test/tools`. The latter directory is where the test helper libraries are located, the most important of which is `libtest.sh`. +The test suite requires `stty -tostop` to be set in the running terminal, +which is typically the default. + Options ------- From ccbda97bda65810cd416b5b4fbf7127c2e0aa951 Mon Sep 17 00:00:00 2001 From: Roland Walker Date: Mon, 21 May 2018 14:12:35 -0400 Subject: [PATCH 2/2] clean up all child processes at exit --- src/tig.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tig.c b/src/tig.c index 7b9e417b8..500f5febb 100644 --- a/src/tig.c +++ b/src/tig.c @@ -738,6 +738,14 @@ die_if_failed(enum status_code code, const char *msg) die("%s: %s", msg, get_status_message(code)); } +void +hangup_children(void) +{ + if (signal(SIGHUP, SIG_IGN) == SIG_ERR) + return; + killpg(getpid(), SIGHUP); +} + static inline enum status_code handle_git_prefix(void) { @@ -774,6 +782,8 @@ main(int argc, const char *argv[]) init_tty(); + atexit(hangup_children); + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) die("Failed to setup signal handler");