Kernel: Make signals more POSIX

This commit is contained in:
Bananymous 2023-07-21 19:54:37 +03:00
parent ad756c36fc
commit 2149cec29f
6 changed files with 52 additions and 14 deletions

View File

@ -155,11 +155,15 @@ namespace Kernel
BAN::Vector<BAN::UniqPtr<FixedWidthAllocator>> m_fixed_width_allocators; BAN::Vector<BAN::UniqPtr<FixedWidthAllocator>> m_fixed_width_allocators;
BAN::UniqPtr<GeneralAllocator> m_general_allocator; BAN::UniqPtr<GeneralAllocator> m_general_allocator;
vaddr_t m_signal_handlers[_SIGMAX + 1] { };
userspace_info_t m_userspace_info; userspace_info_t m_userspace_info;
ExitStatus m_exit_status; ExitStatus m_exit_status;
BAN::UniqPtr<PageTable> m_page_table; BAN::UniqPtr<PageTable> m_page_table;
BAN::RefPtr<TTY> m_tty; BAN::RefPtr<TTY> m_tty;
friend class Thread;
}; };
} }

View File

@ -37,6 +37,7 @@ namespace Kernel
BAN::ErrorOr<Thread*> clone(Process*, uintptr_t rsp, uintptr_t rip); BAN::ErrorOr<Thread*> clone(Process*, uintptr_t rsp, uintptr_t rip);
void setup_exec(); void setup_exec();
bool has_signal_to_execute() const;
void handle_next_signal(); void handle_next_signal();
void handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip); void handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip);
@ -89,8 +90,8 @@ namespace Kernel
bool m_is_userspace { false }; bool m_is_userspace { false };
BAN::CircularQueue<int, 10> m_signal_queue; BAN::CircularQueue<int, 10> m_signal_queue;
vaddr_t m_signal_handlers[_SIGMAX + 1] { }; uint64_t m_signal_mask { 0 };
uint64_t m_signal_mask { (1ull << SIGCHLD) | (1ull << SIGURG) }; bool m_handling_signal { false };
static_assert(_SIGMAX < 64); static_assert(_SIGMAX < 64);
friend class Process; friend class Process;

View File

@ -97,7 +97,10 @@ namespace Kernel
, m_open_file_descriptors(m_credentials) , m_open_file_descriptors(m_credentials)
, m_pid(pid) , m_pid(pid)
, m_tty(TTY::current()) , m_tty(TTY::current())
{ } {
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
m_signal_handlers[i] = (vaddr_t)SIG_DFL;
}
Process::~Process() Process::~Process()
{ {
@ -303,6 +306,7 @@ namespace Kernel
forked->m_fixed_width_allocators = BAN::move(fixed_width_allocators); forked->m_fixed_width_allocators = BAN::move(fixed_width_allocators);
forked->m_general_allocator = BAN::move(general_allocator); forked->m_general_allocator = BAN::move(general_allocator);
forked->m_userspace_info = m_userspace_info; forked->m_userspace_info = m_userspace_info;
memcpy(forked->m_signal_handlers, m_signal_handlers, sizeof(m_signal_handlers));
ASSERT(this == &Process::current()); ASSERT(this == &Process::current());
// FIXME: this should be able to fail // FIXME: this should be able to fail
@ -352,6 +356,9 @@ namespace Kernel
m_userspace_info.entry = elf->file_header_native().e_entry; m_userspace_info.entry = elf->file_header_native().e_entry;
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
m_signal_handlers[i] = (vaddr_t)SIG_DFL;
// NOTE: we clear the elf since we don't need the memory anymore // NOTE: we clear the elf since we don't need the memory anymore
elf.clear(); elf.clear();
@ -789,6 +796,16 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_signal(int signal, void (*handler)(int))
{
if (signal < _SIGMIN || signal > _SIGMAX)
return BAN::Error::from_errno(EINVAL);
CriticalScope _;
m_signal_handlers[signal] = (vaddr_t)handler;
return 0;
}
BAN::ErrorOr<long> Process::sys_kill(pid_t pid, int signal, uintptr_t& return_rsp, uintptr_t& return_rip) BAN::ErrorOr<long> Process::sys_kill(pid_t pid, int signal, uintptr_t& return_rsp, uintptr_t& return_rip)
{ {
if (pid <= 0) if (pid <= 0)

View File

@ -212,7 +212,7 @@ namespace Kernel
current.set_started(); current.set_started();
start_thread(current.rsp(), current.rip()); start_thread(current.rsp(), current.rip());
case Thread::State::Executing: case Thread::State::Executing:
while (!current.m_signal_queue.empty()) while (current.has_signal_to_execute())
current.handle_next_signal(); current.handle_next_signal();
continue_thread(current.rsp(), current.rip()); continue_thread(current.rsp(), current.rip());
case Thread::State::Terminating: case Thread::State::Terminating:

View File

@ -133,6 +133,8 @@ namespace Kernel
m_rsp = stack_base() + stack_size(); m_rsp = stack_base() + stack_size();
m_rip = (uintptr_t)entry_trampoline; m_rip = (uintptr_t)entry_trampoline;
// Signal mask is inherited
// Setup stack for returning // Setup stack for returning
{ {
// FIXME: don't use PageTableScope // FIXME: don't use PageTableScope
@ -143,6 +145,11 @@ namespace Kernel
} }
} }
bool Thread::has_signal_to_execute() const
{
return !m_signal_queue.empty() && !m_handling_signal;
}
void Thread::handle_next_signal() void Thread::handle_next_signal()
{ {
ASSERT(!interrupts_enabled()); ASSERT(!interrupts_enabled());
@ -158,16 +165,24 @@ namespace Kernel
ASSERT(!m_signal_queue.empty()); ASSERT(!m_signal_queue.empty());
ASSERT(m_signal_queue.front() == signal); ASSERT(m_signal_queue.front() == signal);
// Skip masked (ignored) signals vaddr_t signal_handler = process().m_signal_handlers[signal];
if (m_signal_mask & (1ull << signal))
return;
if (m_signal_handlers[signal]) m_handling_signal = true;
// Skip masked and ignored signals
if (m_signal_mask & (1ull << signal))
;
else if (signal_handler == (vaddr_t)SIG_IGN)
;
else if (signal_handler != (vaddr_t)SIG_DFL)
{ {
write_to_stack(return_rsp, return_rip); write_to_stack(return_rsp, return_rip);
write_to_stack(return_rsp, signal); write_to_stack(return_rsp, signal);
write_to_stack(return_rsp, m_signal_handlers[signal]); write_to_stack(return_rsp, signal_handler);
return_rip = (uintptr_t)signal_trampoline; return_rip = (uintptr_t)signal_trampoline;
// FIXME: we should only mark this signal as done when
// handler returns
} }
else else
{ {
@ -226,6 +241,7 @@ namespace Kernel
} }
m_signal_queue.pop(); m_signal_queue.pop();
m_handling_signal = false;
} }
void Thread::validate_stack() const void Thread::validate_stack() const

View File

@ -9,10 +9,10 @@ __BEGIN_DECLS
#include <time.h> #include <time.h>
#define SIG_DFL 1 #define SIG_DFL ((void (*)(int))0)
#define SIG_ERR 2 #define SIG_ERR ((void (*)(int))1)
#define SIG_HOLD 3 #define SIG_HOLD ((void (*)(int))2)
#define SIG_IGN 4 #define SIG_IGN ((void (*)(int))3)
#define __need_pthread_t #define __need_pthread_t
#define __need_size_t #define __need_size_t