Restore terminal foreground process group on exit

Fixes https://github.com/fish-shell/fish-shell/issues/197
This commit is contained in:
ridiculousfish 2012-11-18 02:16:14 -08:00
parent b79854ad1a
commit c9c2fc5ee3
6 changed files with 45 additions and 3 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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();

View file

@ -351,6 +351,7 @@ 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.
This is called from a signal handler.
*/
static void mark_process_status( const job_t *j,
process_t *p,

View file

@ -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

View file

@ -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.
@ -573,6 +581,15 @@ void signal_set_handlers()
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
{