1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 19:58:11 +00:00

Kernel: Implement sigsuspend using a SignalBlocker

`sigsuspend` was previously implemented using a poll on an empty set of
file descriptors. However, this broke quite a few assumptions in
`SelectBlocker`, as it verifies at least one file descriptor to be
ready after waking up and as it relies on being notified by the file
descriptor.

A bare-bones `sigsuspend` may also be implemented by relying on any of
the `sigwait` functions, but as `sigsuspend` features several (currently
unimplemented) restrictions on how returns work, it is a syscall on its
own.
This commit is contained in:
Tim Schumacher 2022-05-13 13:15:45 +02:00 committed by Brian Gianforcaro
parent edbffb3c7a
commit cf0ad3715e
4 changed files with 28 additions and 1 deletions

View file

@ -326,4 +326,28 @@ ErrorOr<FlatPtr> Process::sys$sigtimedwait(Userspace<sigset_t const*> set, Users
return info_value.si_signo;
}
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html
ErrorOr<FlatPtr> Process::sys$sigsuspend(Userspace<sigset_t const*> mask)
{
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
auto sigmask = TRY(copy_typed_from_user(mask));
auto* current_thread = Thread::current();
u32 previous_signal_mask = current_thread->update_signal_mask(sigmask);
ScopeGuard rollback_signal_mask([&]() {
current_thread->update_signal_mask(previous_signal_mask);
});
// TODO: Ensure that/check if we never return if the action is to terminate the process.
// TODO: Ensure that/check if we only return after an eventual signal-catching function returns.
Thread::BlockTimeout timeout = {};
siginfo_t siginfo = {};
if (current_thread->block<Thread::SignalBlocker>(timeout, ~sigmask, siginfo).was_interrupted())
return EINTR;
return 0;
}
}