diff --git a/common.cpp b/common.cpp index de1c06124..fce8c459e 100644 --- a/common.cpp +++ b/common.cpp @@ -1917,6 +1917,9 @@ void configure_thread_assertions_for_testing(void) { /* Notice when we've forked */ static pid_t initial_pid = 0; +/* Be able to restore the term's foreground process group */ +static pid_t initial_foreground_process_group = -1; + bool is_forked_child(void) { /* Just bail if nobody's called setup_fork_guards - e.g. fishd */ if (! initial_pid) return false; @@ -1929,11 +1932,25 @@ bool is_forked_child(void) { return is_child_of_fork; } -void setup_fork_guards(void) { +void setup_fork_guards(void) +{ /* Notice when we fork by stashing our pid. This seems simpler than pthread_atfork(). */ initial_pid = getpid(); } +void save_term_foreground_process_group(void) +{ + initial_foreground_process_group = tcgetpgrp(STDIN_FILENO); +} + +void restore_term_foreground_process_group(void) +{ + if (initial_foreground_process_group != -1) + { + tcsetpgrp(STDIN_FILENO, initial_foreground_process_group); + } +} + bool is_main_thread() { assert (main_thread_id != 0); return main_thread_id == pthread_self(); diff --git a/common.h b/common.h index b0bf0593c..9cb574886 100644 --- a/common.h +++ b/common.h @@ -729,6 +729,10 @@ void configure_thread_assertions_for_testing(); /** Set up a guard to complain if we try to do certain things (like take a lock) after calling fork */ void setup_fork_guards(void); +/** Save the value of tcgetpgrp so we can restore it on exit */ +void save_term_foreground_process_group(void); +void restore_term_foreground_process_group(void); + /** Return whether we are the child of a fork */ bool is_forked_child(void); void assert_is_not_forked_child(const char *who); diff --git a/fish.cpp b/fish.cpp index d1699d584..08fc25441 100644 --- a/fish.cpp +++ b/fish.cpp @@ -444,6 +444,7 @@ int main( int argc, char **argv ) set_main_thread(); setup_fork_guards(); + save_term_foreground_process_group(); wsetlocale( LC_ALL, L"" ); is_interactive_session=1; @@ -468,7 +469,6 @@ int main( int argc, char **argv ) proc_init(); event_init(); wutil_init(); - //parser_init(); builtin_init(); function_init(); env_init(&paths); @@ -554,6 +554,7 @@ int main( int argc, char **argv ) proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res ); + restore_term_foreground_process_group(); history_destroy(); proc_destroy(); builtin_destroy(); diff --git a/proc.cpp b/proc.cpp index deeb0ed8d..7e6cb1a1f 100644 --- a/proc.cpp +++ b/proc.cpp @@ -350,7 +350,8 @@ int job_signal( job_t *j, int signal ) /** Store the status of the process pid that was returned by waitpid. - Return 0 if all went well, nonzero otherwise. + Return 0 if all went well, nonzero otherwise. + This is called from a signal handler. */ static void mark_process_status( const job_t *j, process_t *p, diff --git a/reader.cpp b/reader.cpp index 4102aa289..9be18caa3 100644 --- a/reader.cpp +++ b/reader.cpp @@ -1666,6 +1666,7 @@ static void reader_interactive_init() common_handle_winch(0); + if( tcsetattr(0,TCSANOW,&shell_modes)) /* set the new modes */ { wperror(L"tcsetattr"); @@ -2445,6 +2446,7 @@ static void handle_end_loop() } else { + /* PCA: we used to only hangup jobs if stdin was closed. This prevented child processes from exiting. It's unclear to my why it matters if stdin is closed, but it seems to me if we're forcing an exit, we definitely want to hang up our processes. See https://github.com/fish-shell/fish-shell/issues/138 diff --git a/signal.cpp b/signal.cpp index 2c51e9d2f..98883bf4e 100644 --- a/signal.cpp +++ b/signal.cpp @@ -458,6 +458,14 @@ static void handle_hup( int sig, siginfo_t *info, void *context ) } } +/** Handle sigterm. The only thing we do is restore the front process ID, then die. */ +static void handle_term( int sig, siginfo_t *info, void *context ) +{ + restore_term_foreground_process_group(); + signal(SIGTERM, SIG_DFL); + raise(SIGTERM); +} + /** Interactive mode ^C handler. Respond to int signal by setting interrupted-flag and stopping all loops and conditionals. @@ -572,6 +580,15 @@ void signal_set_handlers() wperror( L"sigaction" ); FATAL_EXIT(); } + + // SIGTERM restores the terminal controlling process before dying + act.sa_flags = SA_SIGINFO; + act.sa_sigaction= &handle_term; + if( sigaction( SIGTERM, &act, 0 ) ) + { + wperror( L"sigaction" ); + FATAL_EXIT(); + } } else