1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 15:07:45 +00:00

Shell: Ignore SIGCHLD after a few unsuccessful attempts at handling it

As noted by the comment, a stray SIGCHLD can make the shell go into an
infinite loop, pretend the signal doesn't exist after trying 10 times in
5ms.
This commit is contained in:
Ali Mohammad Pur 2022-06-24 12:02:19 +04:30 committed by Linus Groh
parent eb4ea45822
commit d338d2b59b

View file

@ -2082,13 +2082,26 @@ void Shell::notify_child_event()
// The child might still be alive (and even running) when this signal is dispatched to us // The child might still be alive (and even running) when this signal is dispatched to us
// so just...repeat until we find a suitable child. // so just...repeat until we find a suitable child.
// This, of course, will mean that someone can send us a SIGCHILD and we'd be spinning here // This, of course, will mean that someone can send us a SIGCHILD and we'd be spinning here
// until the next child event we can actually handle. // until the next child event we can actually handle, so stop after spending a total of 5110us (~5ms) on it.
bool found_child = false; bool found_child = false;
do { size_t const max_tries = 10;
size_t valid_attempts = max_tries;
useconds_t backoff_usec = 20;
int backoff_multiplier = 2;
for (;;) {
if (found_child || --valid_attempts == 0)
break;
// Ignore stray SIGCHLD when there are no jobs. // Ignore stray SIGCHLD when there are no jobs.
if (jobs.is_empty()) if (jobs.is_empty())
return; return;
if (valid_attempts < max_tries - 1) {
usleep(backoff_usec);
backoff_usec *= backoff_multiplier;
}
for (auto& it : jobs) { for (auto& it : jobs) {
auto job_id = it.key; auto job_id = it.key;
auto& job = *it.value; auto& job = *it.value;
@ -2141,7 +2154,7 @@ void Shell::notify_child_event()
for (auto job_id : disowned_jobs) { for (auto job_id : disowned_jobs) {
jobs.remove(job_id); jobs.remove(job_id);
} }
} while (!found_child); }
} }
Shell::Shell() Shell::Shell()