forked from Bananymous/banan-os
Kernel: Make signals more POSIX
This commit is contained in:
parent
ad756c36fc
commit
2149cec29f
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
@ -88,9 +89,9 @@ namespace Kernel
|
||||||
bool m_in_syscall { false };
|
bool m_in_syscall { false };
|
||||||
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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue