mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Restore terminal foreground process group on exit
Fixes https://github.com/fish-shell/fish-shell/issues/197
This commit is contained in:
parent
b79854ad1a
commit
c9c2fc5ee3
6 changed files with 45 additions and 3 deletions
19
common.cpp
19
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();
|
||||
|
|
4
common.h
4
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);
|
||||
|
|
3
fish.cpp
3
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();
|
||||
|
|
3
proc.cpp
3
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,
|
||||
|
|
|
@ -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
|
||||
|
|
17
signal.cpp
17
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
|
||||
|
|
Loading…
Reference in a new issue