mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 14:40:37 +08:00
Repair control-C cancellation of loops
Commit ab189a75
introduced a regression where we stop breaking out
of loops in response to a child death via a signal. Fix that regression.
Also introduces a test to help ensure we don't regress in the future.
Fixes #3780
This commit is contained in:
parent
98b561929f
commit
1d9cc12984
|
@ -757,6 +757,15 @@ static void test_cancellation() {
|
|||
test_1_cancellation(L"while true ; echo nothing > /dev/null; end");
|
||||
test_1_cancellation(L"for i in (while true ; end) ; end");
|
||||
|
||||
// Ensure that if child processes SIGINT, we exit our loops
|
||||
// Test for #3780
|
||||
// Ugly hack - temporarily set is_interactive_session
|
||||
// else we will SIGINT ourselves in response to our child death
|
||||
scoped_push<int> iis(&is_interactive_session, 1);
|
||||
const wchar_t *child_self_destructor = L"while true ; sh -c 'sleep .25; kill -s INT $$' ; end";
|
||||
parser_t::principal_parser().eval(child_self_destructor, io_chain_t(), TOP);
|
||||
iis.restore();
|
||||
|
||||
// Restore signal handling.
|
||||
proc_pop_interactive();
|
||||
signal_reset_handlers();
|
||||
|
|
|
@ -299,9 +299,8 @@ void job_mark_process_as_failed(job_t *job, const process_t *failed_proc) {
|
|||
/// \param pid the pid of the process whose status changes
|
||||
/// \param status the status as returned by wait
|
||||
static void handle_child_status(pid_t pid, int status) {
|
||||
bool found_proc = false;
|
||||
job_t *j = NULL;
|
||||
process_t *p = NULL;
|
||||
const process_t *found_proc = NULL;
|
||||
|
||||
job_iterator_t jobs;
|
||||
while (!found_proc && (j = jobs.next())) {
|
||||
|
@ -312,7 +311,7 @@ static void handle_child_status(pid_t pid, int status) {
|
|||
if (p->completed && prev && !prev->completed && prev->pid) {
|
||||
kill(prev->pid, SIGPIPE);
|
||||
}
|
||||
found_proc = true;
|
||||
found_proc = p.get();
|
||||
break;
|
||||
}
|
||||
prev = p.get();
|
||||
|
@ -327,7 +326,7 @@ static void handle_child_status(pid_t pid, int status) {
|
|||
if (is_interactive_session) {
|
||||
// In an interactive session, tell the principal parser to skip all blocks we're executing
|
||||
// so control-C returns control to the user.
|
||||
if (p && found_proc) parser_t::skip_all_blocks();
|
||||
if (found_proc) parser_t::skip_all_blocks();
|
||||
} else {
|
||||
// Deliver the SIGINT or SIGQUIT signal to ourself since we're not interactive.
|
||||
struct sigaction act;
|
||||
|
|
Loading…
Reference in New Issue
Block a user