mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-24 10:22:05 -05:00
Shell: Handle SIGCHLD after sending SIGCONT to job
This fixes `fg` and `bg` causing the shell to go into an infinite loop of trying to `waitpid` until some current job changes state. a.k.a. "Fix Shell backgrounding, yet again!" :P
This commit is contained in:
parent
50f5959996
commit
5d19509616
3 changed files with 12 additions and 3 deletions
|
@ -111,7 +111,7 @@ int Shell::builtin_bg(int argc, const char** argv)
|
||||||
|
|
||||||
job->set_running_in_background(true);
|
job->set_running_in_background(true);
|
||||||
job->set_should_announce_exit(true);
|
job->set_should_announce_exit(true);
|
||||||
job->set_is_suspended(false);
|
job->set_shell_did_continue(true);
|
||||||
|
|
||||||
dbgln("Resuming {} ({})", job->pid(), job->cmd());
|
dbgln("Resuming {} ({})", job->pid(), job->cmd());
|
||||||
warnln("Resuming job {} - {}", job->job_id(), job->cmd().characters());
|
warnln("Resuming job {} - {}", job->job_id(), job->cmd().characters());
|
||||||
|
@ -396,7 +396,7 @@ int Shell::builtin_fg(int argc, const char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
job->set_running_in_background(false);
|
job->set_running_in_background(false);
|
||||||
job->set_is_suspended(false);
|
job->set_shell_did_continue(true);
|
||||||
|
|
||||||
dbgln("Resuming {} ({})", job->pid(), job->cmd());
|
dbgln("Resuming {} ({})", job->pid(), job->cmd());
|
||||||
warnln("Resuming job {} - {}", job->job_id(), job->cmd().characters());
|
warnln("Resuming job {} - {}", job->job_id(), job->cmd().characters());
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
bool should_announce_exit() const { return m_should_announce_exit; }
|
bool should_announce_exit() const { return m_should_announce_exit; }
|
||||||
bool should_announce_signal() const { return m_should_announce_signal; }
|
bool should_announce_signal() const { return m_should_announce_signal; }
|
||||||
bool is_suspended() const { return m_is_suspended; }
|
bool is_suspended() const { return m_is_suspended; }
|
||||||
|
bool shell_did_continue() const { return m_shell_did_continue; }
|
||||||
void unblock() const;
|
void unblock() const;
|
||||||
|
|
||||||
Core::ElapsedTimer& timer() { return m_command_timer; }
|
Core::ElapsedTimer& timer() { return m_command_timer; }
|
||||||
|
@ -94,6 +95,7 @@ public:
|
||||||
void set_signalled(int sig);
|
void set_signalled(int sig);
|
||||||
|
|
||||||
void set_is_suspended(bool value) const { m_is_suspended = value; }
|
void set_is_suspended(bool value) const { m_is_suspended = value; }
|
||||||
|
void set_shell_did_continue(bool value) const { m_shell_did_continue = value; }
|
||||||
|
|
||||||
void set_running_in_background(bool running_in_background)
|
void set_running_in_background(bool running_in_background)
|
||||||
{
|
{
|
||||||
|
@ -129,6 +131,7 @@ private:
|
||||||
Core::ElapsedTimer m_command_timer;
|
Core::ElapsedTimer m_command_timer;
|
||||||
mutable bool m_active { true };
|
mutable bool m_active { true };
|
||||||
mutable bool m_is_suspended { false };
|
mutable bool m_is_suspended { false };
|
||||||
|
mutable bool m_shell_did_continue { false };
|
||||||
bool m_should_be_disowned { false };
|
bool m_should_be_disowned { false };
|
||||||
OwnPtr<AST::Command> m_command;
|
OwnPtr<AST::Command> m_command;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1057,7 +1057,7 @@ void Shell::block_on_job(RefPtr<Job> job)
|
||||||
if (!job)
|
if (!job)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (job->is_suspended())
|
if (job->is_suspended() && !job->shell_did_continue())
|
||||||
return; // We cannot wait for a suspended job.
|
return; // We cannot wait for a suspended job.
|
||||||
|
|
||||||
ScopeGuard io_restorer { [&]() {
|
ScopeGuard io_restorer { [&]() {
|
||||||
|
@ -1655,6 +1655,12 @@ void Shell::notify_child_event()
|
||||||
}
|
}
|
||||||
if (child_pid == 0) {
|
if (child_pid == 0) {
|
||||||
// If the child existed, but wasn't dead.
|
// If the child existed, but wasn't dead.
|
||||||
|
if (job.is_suspended() && job.shell_did_continue()) {
|
||||||
|
// The job was suspended, and we sent it a SIGCONT.
|
||||||
|
job.set_is_suspended(false);
|
||||||
|
job.set_shell_did_continue(false);
|
||||||
|
found_child = true;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (child_pid == job.pid()) {
|
if (child_pid == job.pid()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue