diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 7347dbfe7d..72c89d587e 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -170,6 +170,7 @@ enum class NeedsBigProcessLock { S(sigpending, NeedsBigProcessLock::Yes) \ S(sigprocmask, NeedsBigProcessLock::Yes) \ S(sigreturn, NeedsBigProcessLock::Yes) \ + S(sigsuspend, NeedsBigProcessLock::Yes) \ S(sigtimedwait, NeedsBigProcessLock::Yes) \ S(socket, NeedsBigProcessLock::Yes) \ S(socketpair, NeedsBigProcessLock::Yes) \ diff --git a/Kernel/Process.h b/Kernel/Process.h index c5dfc4a96e..d5d85b156d 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -334,6 +334,7 @@ public: ErrorOr sys$sigaltstack(Userspace ss, Userspace old_ss); ErrorOr sys$sigprocmask(int how, Userspace set, Userspace old_set); ErrorOr sys$sigpending(Userspace); + ErrorOr sys$sigsuspend(Userspace); ErrorOr sys$sigtimedwait(Userspace, Userspace, Userspace); ErrorOr sys$getgroups(size_t, Userspace); ErrorOr sys$setgroups(size_t, Userspace); diff --git a/Kernel/Syscalls/sigaction.cpp b/Kernel/Syscalls/sigaction.cpp index 2226e816bd..63456e2971 100644 --- a/Kernel/Syscalls/sigaction.cpp +++ b/Kernel/Syscalls/sigaction.cpp @@ -326,4 +326,28 @@ ErrorOr Process::sys$sigtimedwait(Userspace set, Users return info_value.si_signo; } +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html +ErrorOr Process::sys$sigsuspend(Userspace 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(timeout, ~sigmask, siginfo).was_interrupted()) + return EINTR; + + return 0; +} + } diff --git a/Userland/Libraries/LibC/signal.cpp b/Userland/Libraries/LibC/signal.cpp index 37fba25965..7291059fdc 100644 --- a/Userland/Libraries/LibC/signal.cpp +++ b/Userland/Libraries/LibC/signal.cpp @@ -175,7 +175,8 @@ void siglongjmp(jmp_buf env, int val) // https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html int sigsuspend(sigset_t const* set) { - return pselect(0, nullptr, nullptr, nullptr, nullptr, set); + int rc = syscall(SC_sigsuspend, set); + __RETURN_WITH_ERRNO(rc, rc, -1); } // https://pubs.opengroup.org/onlinepubs/009604499/functions/sigwait.html