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:
parent
34e680d792
commit
808c97020a
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue