Kernel/LibC: Implement SA_RESTART

I have been thinking how to do this for a long time but I finally
figured out a semi-clean way
This commit is contained in:
Bananymous 2025-04-22 02:42:44 +03:00
parent 34e680d792
commit 808c97020a
6 changed files with 16 additions and 7 deletions

View File

@ -53,7 +53,8 @@ namespace Kernel
// Returns true if pending signal can be added to thread // Returns true if pending signal can be added to thread
bool can_add_signal_to_execute() const; bool can_add_signal_to_execute() const;
bool will_execute_signal() const; bool will_execute_signal() const;
void handle_signal(int signal = 0); // Returns true if handled signal had SA_RESTART
bool handle_signal(int signal = 0);
bool add_signal(int signal); bool add_signal(int signal);
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout // blocks current thread and returns either on unblock, eintr, spuriously or after timeout

View File

@ -2073,9 +2073,7 @@ namespace Kernel
if (act) if (act)
{ {
if (act->sa_flags == SA_RESTART) if (act->sa_flags & ~(SA_RESTART))
dwarnln("FIXME: sigaction ignoring SA_RESTART", signal, act->sa_flags);
else if (act->sa_flags)
{ {
dwarnln("TODO: sigaction({}, {H})", signal, act->sa_flags); dwarnln("TODO: sigaction({}, {H})", signal, act->sa_flags);
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);

View File

@ -79,7 +79,9 @@ namespace Kernel
auto& current_thread = Thread::current(); auto& current_thread = Thread::current();
if (current_thread.can_add_signal_to_execute()) if (current_thread.can_add_signal_to_execute())
current_thread.handle_signal(); if (current_thread.handle_signal())
if (ret.is_error() && ret.error().get_error_code() == EINTR)
ret = BAN::Error::from_errno(ERESTART);
ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing); ASSERT(Kernel::Thread::current().state() == Kernel::Thread::State::Executing);

View File

@ -435,7 +435,7 @@ namespace Kernel
return interrupt_stack.ip == (uintptr_t)signal_trampoline; return interrupt_stack.ip == (uintptr_t)signal_trampoline;
} }
void Thread::handle_signal(int signal) bool Thread::handle_signal(int signal)
{ {
ASSERT(&Thread::current() == this); ASSERT(&Thread::current() == this);
ASSERT(is_userspace()); ASSERT(is_userspace());
@ -463,10 +463,12 @@ namespace Kernel
} }
vaddr_t signal_handler; vaddr_t signal_handler;
bool has_sa_restart;
{ {
SpinLockGuard _(m_process->m_signal_lock); SpinLockGuard _(m_process->m_signal_lock);
ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO)); ASSERT(!(m_process->m_signal_handlers[signal].sa_flags & SA_SIGINFO));
signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler; signal_handler = (vaddr_t)m_process->m_signal_handlers[signal].sa_handler;
has_sa_restart = !!(m_process->m_signal_handlers[signal].sa_flags & SA_RESTART);
} }
m_signal_pending_mask &= ~(1ull << signal); m_signal_pending_mask &= ~(1ull << signal);
@ -534,6 +536,8 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
} }
return has_sa_restart;
} }
bool Thread::add_signal(int signal) bool Thread::add_signal(int signal)

View File

@ -90,6 +90,7 @@ __BEGIN_DECLS
#define EXDEV 81 #define EXDEV 81
#define ENOTBLK 82 #define ENOTBLK 82
#define ERESTART 0xFE /* internal errno for SA_RESTART */
#define EUNKNOWN 0xFF #define EUNKNOWN 0xFF
#define errno (*__errno_location()) #define errno (*__errno_location())

View File

@ -83,7 +83,10 @@ long syscall(long syscall, ...)
va_end(args); va_end(args);
long ret = Kernel::syscall(syscall, arg1, arg2, arg3, arg4, arg5); long ret;
do
ret = Kernel::syscall(syscall, arg1, arg2, arg3, arg4, arg5);
while (ret == -ERESTART);
if (ret < 0) if (ret < 0)
{ {