diff --git a/src/fish_test_helper.cpp b/src/fish_test_helper.cpp index de19d970d..e1224d6cb 100644 --- a/src/fish_test_helper.cpp +++ b/src/fish_test_helper.cpp @@ -113,6 +113,23 @@ static void print_ignored_signals() { } } +static void print_stop_cont() { + signal(SIGTSTP, [](int) { + write(STDOUT_FILENO, "SIGTSTP\n", strlen("SIGTSTP\n")); + kill(getpid(), SIGSTOP); + }); + signal(SIGCONT, [](int) { + write(STDOUT_FILENO, "SIGCONT\n", strlen("SIGCONT\n")); + }); + char buff[1]; + for (;;) { + if (read(STDIN_FILENO, buff, sizeof buff) >= 0) { + exit(0); + } + } + +} + static void show_help(); /// A thing that fish_test_helper can do. @@ -142,6 +159,7 @@ static fth_command_t s_commands[] = { "Print to stdout the name(s) of blocked signals"}, {"print_ignored_signals", print_ignored_signals, "Print to stdout the name(s) of ignored signals"}, + {"print_stop_cont", print_stop_cont, "Print when we get SIGTSTP and SIGCONT, exiting on input"}, {"help", show_help, "Print list of fish_test_helper commands"}, }; diff --git a/src/reader.cpp b/src/reader.cpp index 144995f96..4edb9814f 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -2720,11 +2720,14 @@ struct readline_loop_state_t { /// Run a sequence of commands from an input binding. void reader_data_t::run_input_command_scripts(const wcstring_list_t &cmds) { + // Need to donate/steal the tty - see #2214. + term_donate(outputter_t::stdoutput()); auto last_statuses = parser().get_last_statuses(); for (const wcstring &cmd : cmds) { parser().eval(cmd, io_chain_t{}); } parser().set_last_statuses(std::move(last_statuses)); + term_steal(); } /// Read normal characters, inserting them into the command line. diff --git a/tests/pexpects/fg2.py b/tests/pexpects/fg2.py index b0f2be4a0..a02d5429e 100644 --- a/tests/pexpects/fg2.py +++ b/tests/pexpects/fg2.py @@ -43,3 +43,31 @@ expect_prompt("has stopped") sendline("fg") sleep(0.1) # allow tty to transfer send("\x03") # control-c to cancel it + +expect_prompt() +sendline("jobs") +expect_prompt("jobs: There are no jobs") + +# Regression test for #2214: foregrounding from a key binding works! +sendline(r"bind \cr 'fg >/dev/null 2>/dev/null'") +expect_prompt() +sendline("$fish_test_helper print_stop_cont"); +sleep(0.2) + +send("\x1A") # ctrl-z +expect_prompt("SIGTSTP") +sleep(0.1) +send("\x12") # ctrl-r, placing fth in foreground +expect_str("SIGCONT") + +# Do it again. +send("\x1A") +expect_str("SIGTSTP") +sleep(0.1) +send("\x12") +expect_str("SIGCONT") + +# End fth by sending it anything. +send("\x12") +sendline("derp") +expect_prompt()