mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-15 06:24:01 +00: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
2 changed files with 31 additions and 16 deletions
40
src/exec.cpp
40
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;
|
tnode_t<grammar::statement> node = p->internal_block_node;
|
||||||
assert(source && node && "Process is missing node info");
|
assert(source && node && "Process is missing node info");
|
||||||
return [=](parser_t &parser) {
|
return [=](parser_t &parser) {
|
||||||
parser.eval_node(source, node, TOP, lineage);
|
eval_result_t res = parser.eval_node(source, node, TOP, lineage);
|
||||||
int status = parser.get_last_status();
|
switch (res) {
|
||||||
// FIXME: setting the status this way is dangerous nonsense, we need to decode the
|
case eval_result_t::ok:
|
||||||
// status properly if it was a signal.
|
case eval_result_t::error:
|
||||||
return proc_status_t::from_exit_code(status);
|
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 {
|
} else {
|
||||||
assert(p->type == process_type_t::function);
|
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();
|
const auto &ld = parser.libdata();
|
||||||
auto saved_exec_count = ld.exec_count;
|
auto saved_exec_count = ld.exec_count;
|
||||||
const block_t *fb = function_prepare_environment(parser, *argv, *props);
|
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);
|
function_restore_environment(parser, fb);
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case eval_result_t::ok:
|
||||||
// If the function did not execute anything, treat it as success.
|
// If the function did not execute anything, treat it as success.
|
||||||
int status;
|
return proc_status_t::from_exit_code(saved_exec_count == ld.exec_count
|
||||||
if (saved_exec_count == ld.exec_count) {
|
? EXIT_SUCCESS
|
||||||
status = 0;
|
: parser.get_last_status());
|
||||||
} else {
|
case eval_result_t::error:
|
||||||
status = parser.get_last_status();
|
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
|
case eval_result_t::cancelled:
|
||||||
// status properly if it was a signal.
|
// TODO: we should reflect the actual signal which was received.
|
||||||
return proc_status_t::from_exit_code(status);
|
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 */));
|
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).
|
/// \return if we are stopped (as in SIGSTOP).
|
||||||
bool stopped() const { return WIFSTOPPED(status_); }
|
bool stopped() const { return WIFSTOPPED(status_); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue