mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:27:35 +00:00
Shell: Make interrupts kill the whole chain and not just the current job
This makes interrupting `sleep 10; echo hi` not print `hi` anymore, which is the expected behaviour anyway. Also fixes the problem with fast-running loops "eating" interrupts and not quitting.
This commit is contained in:
parent
abaee3a325
commit
ea66750640
3 changed files with 33 additions and 13 deletions
|
@ -1190,7 +1190,7 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shell->has_error(Shell::ShellError::None))
|
if (shell->has_any_error() && !shell->has_error(Shell::ShellError::InternalControlFlowInterrupted))
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
||||||
if (block_value->is_job()) {
|
if (block_value->is_job()) {
|
||||||
|
@ -1199,13 +1199,12 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
shell->block_on_job(job);
|
shell->block_on_job(job);
|
||||||
|
|
||||||
if (job->signaled()) {
|
if (shell->has_any_error()) {
|
||||||
if (job->termination_signal() == SIGINT)
|
if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted))
|
||||||
++consecutive_interruptions;
|
++consecutive_interruptions;
|
||||||
else
|
|
||||||
|
if (shell->has_error(Shell::ShellError::InternalControlFlowKilled))
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
} else {
|
|
||||||
consecutive_interruptions = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
@ -1216,11 +1215,16 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
|
||||||
Optional<StringView> index_name = m_index_variable.has_value() ? Optional<StringView>(m_index_variable->name) : Optional<StringView>();
|
Optional<StringView> index_name = m_index_variable.has_value() ? Optional<StringView>(m_index_variable->name) : Optional<StringView>();
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
m_iterated_expression->for_each_entry(shell, [&](auto value) {
|
m_iterated_expression->for_each_entry(shell, [&](auto value) {
|
||||||
if (consecutive_interruptions == 2)
|
if (consecutive_interruptions >= 2)
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
||||||
if (shell && shell->has_any_error())
|
if (shell) {
|
||||||
return IterationDecision::Break;
|
if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted))
|
||||||
|
shell->take_error();
|
||||||
|
|
||||||
|
if (shell->has_any_error())
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<Value> block_value;
|
RefPtr<Value> block_value;
|
||||||
|
|
||||||
|
@ -1240,11 +1244,16 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (shell && shell->has_any_error())
|
if (consecutive_interruptions >= 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (consecutive_interruptions == 2)
|
if (shell) {
|
||||||
break;
|
if (shell->has_error(Shell::ShellError::InternalControlFlowInterrupted))
|
||||||
|
shell->take_error();
|
||||||
|
|
||||||
|
if (shell->has_any_error())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<Value> block_value = m_block->run(shell);
|
RefPtr<Value> block_value = m_block->run(shell);
|
||||||
if (run(block_value) == IterationDecision::Break)
|
if (run(block_value) == IterationDecision::Break)
|
||||||
|
|
|
@ -1765,7 +1765,12 @@ void Shell::notify_child_event()
|
||||||
}
|
}
|
||||||
if (child_pid == job.pid()) {
|
if (child_pid == job.pid()) {
|
||||||
if (WIFSIGNALED(wstatus) && !WIFSTOPPED(wstatus)) {
|
if (WIFSIGNALED(wstatus) && !WIFSTOPPED(wstatus)) {
|
||||||
job.set_signalled(WTERMSIG(wstatus));
|
auto signal = WTERMSIG(wstatus);
|
||||||
|
job.set_signalled(signal);
|
||||||
|
if (signal == SIGINT)
|
||||||
|
raise_error(ShellError::InternalControlFlowInterrupted, "Interrupted"sv, job.command().position);
|
||||||
|
else if (signal == SIGKILL)
|
||||||
|
raise_error(ShellError::InternalControlFlowKilled, "Interrupted"sv, job.command().position);
|
||||||
} else if (WIFEXITED(wstatus)) {
|
} else if (WIFEXITED(wstatus)) {
|
||||||
job.set_has_exit(WEXITSTATUS(wstatus));
|
job.set_has_exit(WEXITSTATUS(wstatus));
|
||||||
} else if (WIFSTOPPED(wstatus)) {
|
} else if (WIFSTOPPED(wstatus)) {
|
||||||
|
@ -1998,6 +2003,8 @@ void Shell::possibly_print_error() const
|
||||||
break;
|
break;
|
||||||
case ShellError::InternalControlFlowBreak:
|
case ShellError::InternalControlFlowBreak:
|
||||||
case ShellError::InternalControlFlowContinue:
|
case ShellError::InternalControlFlowContinue:
|
||||||
|
case ShellError::InternalControlFlowInterrupted:
|
||||||
|
case ShellError::InternalControlFlowKilled:
|
||||||
return;
|
return;
|
||||||
case ShellError::None:
|
case ShellError::None:
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -228,6 +228,8 @@ public:
|
||||||
None,
|
None,
|
||||||
InternalControlFlowBreak,
|
InternalControlFlowBreak,
|
||||||
InternalControlFlowContinue,
|
InternalControlFlowContinue,
|
||||||
|
InternalControlFlowInterrupted,
|
||||||
|
InternalControlFlowKilled,
|
||||||
EvaluatedSyntaxError,
|
EvaluatedSyntaxError,
|
||||||
NonExhaustiveMatchRules,
|
NonExhaustiveMatchRules,
|
||||||
InvalidGlobError,
|
InvalidGlobError,
|
||||||
|
@ -260,6 +262,8 @@ public:
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case ShellError::InternalControlFlowBreak:
|
case ShellError::InternalControlFlowBreak:
|
||||||
case ShellError::InternalControlFlowContinue:
|
case ShellError::InternalControlFlowContinue:
|
||||||
|
case ShellError::InternalControlFlowInterrupted:
|
||||||
|
case ShellError::InternalControlFlowKilled:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue