mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-30 07:01:22 -03:00
Correctly propagate signals from cancelled jobs into parse_execution_context
This concerns code like the following:
while true ; sleep 100; end
Here 'while' is a "simple block execution" and does not create a new job,
or get a pgid. Each 'sleep' however is an external command execution, and
is treated as a distinct job. (bash is the same way). So `while` and
`sleep` are always in different job groups.
The problem comes about if 'sleep' is cancelled through SIGINT or SIGQUIT.
Prior to 2a4c545b21, if *any* process got a SIGINT or SIGQUIT, then fish
would mark a global "stop executing" variable. This obviously prevents
background execution of fish functions.
In 2a4c545b21, this was changed so only the job's group gets marked as
cancelled. However in the case of one job group spawning another, we
weren't propagating the signal.
This adds a signal to parse_execution_context which the parser checks after
execution. It's not ideal since now we have three different places where
signals can be recorded. However it fixes this regression which is too
important to leave unfixed for long.
Fixes #7259
This commit is contained in:
@@ -699,12 +699,21 @@ eval_res_t parser_t::eval_node(const parsed_source_ref_t &ps, const T &node,
|
||||
const size_t new_exec_count = libdata().exec_count;
|
||||
const size_t new_status_count = libdata().status_count;
|
||||
|
||||
// Check if the execution context stopped due to a signal from a job it created.
|
||||
// This may come about if the context created a new job group.
|
||||
// TODO: there are way too many signals flying around, we need to rationalize this.
|
||||
int signal_from_exec = execution_context->get_cancel_signal();
|
||||
|
||||
exc.restore();
|
||||
this->pop_block(scope_block);
|
||||
|
||||
job_reap(*this, false); // reap again
|
||||
|
||||
if (int sig = check_cancel_signal()) {
|
||||
if (signal_from_exec) {
|
||||
// A job spawned by the execution context got SIGINT or SIGQUIT, which stopped all
|
||||
// execution.
|
||||
return proc_status_t::from_signal(signal_from_exec);
|
||||
} else if (int sig = check_cancel_signal()) {
|
||||
// We were signalled.
|
||||
return proc_status_t::from_signal(sig);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user