mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-26 02:13:38 +08:00
Correctly set the exit status in block and function processes
Previously, if the user control-C'd out of a process, we would set a bogus exit status in the process, but it was difficult to observe this because we would be cancelling anyways. But set it properly.
This commit is contained in:
parent
b3d2cdc0ff
commit
d4daa28690
42
src/exec.cpp
42
src/exec.cpp
|
@ -753,11 +753,17 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job
|
|||
tnode_t<grammar::statement> node = p->internal_block_node;
|
||||
assert(source && node && "Process is missing node info");
|
||||
return [=](parser_t &parser) {
|
||||
parser.eval_node(source, node, TOP, lineage);
|
||||
int status = parser.get_last_status();
|
||||
// FIXME: setting the status this way is dangerous nonsense, we need to decode the
|
||||
// status properly if it was a signal.
|
||||
return proc_status_t::from_exit_code(status);
|
||||
eval_result_t res = parser.eval_node(source, node, TOP, lineage);
|
||||
switch (res) {
|
||||
case eval_result_t::ok:
|
||||
case eval_result_t::error:
|
||||
return proc_status_t::from_exit_code(parser.get_last_status());
|
||||
case eval_result_t::cancelled:
|
||||
// TODO: we should reflect the actual signal which was received.
|
||||
return proc_status_t::from_signal(SIGINT);
|
||||
case eval_result_t::control_flow:
|
||||
DIE("eval_result_t::control_flow should not be returned from eval_node");
|
||||
}
|
||||
};
|
||||
} else {
|
||||
assert(p->type == process_type_t::function);
|
||||
|
@ -771,20 +777,24 @@ static proc_performer_t get_performer_for_process(process_t *p, const job_t *job
|
|||
const auto &ld = parser.libdata();
|
||||
auto saved_exec_count = ld.exec_count;
|
||||
const block_t *fb = function_prepare_environment(parser, *argv, *props);
|
||||
parser.eval_node(props->parsed_source, props->body_node, TOP, lineage);
|
||||
auto res = parser.eval_node(props->parsed_source, props->body_node, TOP, lineage);
|
||||
function_restore_environment(parser, fb);
|
||||
|
||||
// If the function did not execute anything, treat it as success.
|
||||
int status;
|
||||
if (saved_exec_count == ld.exec_count) {
|
||||
status = 0;
|
||||
} else {
|
||||
status = parser.get_last_status();
|
||||
}
|
||||
switch (res) {
|
||||
case eval_result_t::ok:
|
||||
// If the function did not execute anything, treat it as success.
|
||||
return proc_status_t::from_exit_code(saved_exec_count == ld.exec_count
|
||||
? EXIT_SUCCESS
|
||||
: parser.get_last_status());
|
||||
case eval_result_t::error:
|
||||
return proc_status_t::from_exit_code(parser.get_last_status());
|
||||
|
||||
// FIXME: setting the status this way is dangerous nonsense, we need to decode the
|
||||
// status properly if it was a signal.
|
||||
return proc_status_t::from_exit_code(status);
|
||||
case eval_result_t::cancelled:
|
||||
// TODO: we should reflect the actual signal which was received.
|
||||
return proc_status_t::from_signal(SIGINT);
|
||||
case eval_result_t::control_flow:
|
||||
DIE("eval_result_t::control_flow should not be returned from eval_node");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,11 @@ class proc_status_t {
|
|||
return proc_status_t(w_exitcode(ret, 0 /* sig */));
|
||||
}
|
||||
|
||||
/// Construct directly from a signal.
|
||||
static proc_status_t from_signal(int sig) {
|
||||
return proc_status_t(w_exitcode(0 /* ret */, sig));
|
||||
}
|
||||
|
||||
/// \return if we are stopped (as in SIGSTOP).
|
||||
bool stopped() const { return WIFSTOPPED(status_); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user