forked from Bananymous/banan-os
Kernel: Make signals thread specific
This commit is contained in:
parent
217e5f81cc
commit
a989c44211
|
@ -158,10 +158,6 @@ namespace Kernel
|
||||||
userspace_info_t m_userspace_info;
|
userspace_info_t m_userspace_info;
|
||||||
ExitStatus m_exit_status;
|
ExitStatus m_exit_status;
|
||||||
|
|
||||||
vaddr_t m_signal_handlers[_SIGMAX + 1] { };
|
|
||||||
uint64_t m_signal_mask { (1ull << SIGCHLD) | (1ull << SIGURG) };
|
|
||||||
static_assert(_SIGMAX < 64);
|
|
||||||
|
|
||||||
BAN::UniqPtr<PageTable> m_page_table;
|
BAN::UniqPtr<PageTable> m_page_table;
|
||||||
BAN::RefPtr<TTY> m_tty;
|
BAN::RefPtr<TTY> m_tty;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/CircularQueue.h>
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <BAN/UniqPtr.h>
|
#include <BAN/UniqPtr.h>
|
||||||
#include <kernel/Memory/VirtualRange.h>
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -35,6 +37,8 @@ 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();
|
||||||
|
|
||||||
|
void handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip);
|
||||||
|
|
||||||
pid_t tid() const { return m_tid; }
|
pid_t tid() const { return m_tid; }
|
||||||
|
|
||||||
void set_rsp(uintptr_t rsp) { m_rsp = rsp; validate_stack(); }
|
void set_rsp(uintptr_t rsp) { m_rsp = rsp; validate_stack(); }
|
||||||
|
@ -83,6 +87,12 @@ 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;
|
||||||
|
vaddr_t m_signal_handlers[_SIGMAX + 1] { };
|
||||||
|
uint64_t m_signal_mask { (1ull << SIGCHLD) | (1ull << SIGURG) };
|
||||||
|
static_assert(_SIGMAX < 64);
|
||||||
|
|
||||||
|
friend class Process;
|
||||||
friend class Scheduler;
|
friend class Scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
extern "C" void signal_trampoline();
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -795,81 +793,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (signal < _SIGMIN || signal > _SIGMAX)
|
if (signal < _SIGMIN || signal > _SIGMAX)
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
ASSERT(m_threads.size() == 1);
|
||||||
ASSERT(&Process::current() == this);
|
Thread::current().handle_signal(signal, return_rsp, return_rip);
|
||||||
|
|
||||||
// Skip masked (ignored) signals
|
|
||||||
if (m_signal_mask & (1ull << signal))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
LockGuard lock_guard(m_lock);
|
|
||||||
if (m_signal_handlers[signal])
|
|
||||||
{
|
|
||||||
asm volatile("cli");
|
|
||||||
|
|
||||||
uintptr_t* return_rsp_ptr = (uintptr_t*)return_rsp;
|
|
||||||
*--return_rsp_ptr = return_rip;
|
|
||||||
*--return_rsp_ptr = signal;
|
|
||||||
*--return_rsp_ptr = m_signal_handlers[signal];
|
|
||||||
|
|
||||||
return_rsp = (uintptr_t)return_rsp_ptr;
|
|
||||||
return_rip = (uintptr_t)signal_trampoline;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (signal)
|
|
||||||
{
|
|
||||||
// Abnormal termination of the process with additional actions.
|
|
||||||
case SIGABRT:
|
|
||||||
case SIGBUS:
|
|
||||||
case SIGFPE:
|
|
||||||
case SIGILL:
|
|
||||||
case SIGQUIT:
|
|
||||||
case SIGSEGV:
|
|
||||||
case SIGSYS:
|
|
||||||
case SIGTRAP:
|
|
||||||
case SIGXCPU:
|
|
||||||
case SIGXFSZ:
|
|
||||||
// TODO: additional actions
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
// Abnormal termination of the process
|
|
||||||
case SIGALRM:
|
|
||||||
case SIGHUP:
|
|
||||||
case SIGINT:
|
|
||||||
case SIGKILL:
|
|
||||||
case SIGPIPE:
|
|
||||||
case SIGTERM:
|
|
||||||
case SIGUSR1:
|
|
||||||
case SIGUSR2:
|
|
||||||
case SIGPOLL:
|
|
||||||
case SIGPROF:
|
|
||||||
case SIGVTALRM:
|
|
||||||
{
|
|
||||||
auto message = BAN::String::formatted("killed by signal {}\n", signal);
|
|
||||||
(void)m_tty->write(0, message.data(), message.size());
|
|
||||||
lock_guard.~LockGuard();
|
|
||||||
exit(128 + signal);
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore the signal
|
|
||||||
case SIGCHLD:
|
|
||||||
case SIGURG:
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Stop the process:
|
|
||||||
case SIGTSTP:
|
|
||||||
case SIGTTIN:
|
|
||||||
case SIGTTOU:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
|
|
||||||
// Continue the process, if it is stopped; otherwise, ignore the signal.
|
|
||||||
case SIGCONT:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,23 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
extern "C" void thread_userspace_trampoline(uint64_t rsp, uint64_t rip, int argc, char** argv, char** envp);
|
extern "C" void thread_userspace_trampoline(uint64_t rsp, uint64_t rip, int argc, char** argv, char** envp);
|
||||||
extern "C" uintptr_t read_rip();
|
extern "C" uintptr_t read_rip();
|
||||||
|
|
||||||
template<size_t size, typename T>
|
extern "C" void signal_trampoline();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
static void write_to_stack(uintptr_t& rsp, const T& value)
|
static void write_to_stack(uintptr_t& rsp, const T& value)
|
||||||
{
|
{
|
||||||
rsp -= size;
|
rsp -= sizeof(uintptr_t);
|
||||||
memcpy((void*)rsp, (void*)&value, size);
|
if constexpr(sizeof(T) < sizeof(uintptr_t))
|
||||||
|
*(uintptr_t*)rsp = (uintptr_t)value;
|
||||||
|
else
|
||||||
|
memcpy((void*)rsp, (void*)&value, sizeof(uintptr_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t s_next_tid = 1;
|
static pid_t s_next_tid = 1;
|
||||||
|
@ -36,9 +42,9 @@ namespace Kernel
|
||||||
thread->m_rip = (uintptr_t)entry;
|
thread->m_rip = (uintptr_t)entry;
|
||||||
|
|
||||||
// Initialize stack for returning
|
// Initialize stack for returning
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, thread);
|
write_to_stack(thread->m_rsp, thread);
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, &Thread::on_exit);
|
write_to_stack(thread->m_rsp, &Thread::on_exit);
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, data);
|
write_to_stack(thread->m_rsp, data);
|
||||||
|
|
||||||
thread_deleter.disable();
|
thread_deleter.disable();
|
||||||
|
|
||||||
|
@ -131,12 +137,88 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
// FIXME: don't use PageTableScope
|
// FIXME: don't use PageTableScope
|
||||||
PageTableScope _(m_process->page_table());
|
PageTableScope _(m_process->page_table());
|
||||||
write_to_stack<sizeof(void*)>(m_rsp, this);
|
write_to_stack(m_rsp, this);
|
||||||
write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit);
|
write_to_stack(m_rsp, &Thread::on_exit);
|
||||||
write_to_stack<sizeof(void*)>(m_rsp, nullptr);
|
write_to_stack(m_rsp, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::handle_signal(int signal, uintptr_t& return_rsp, uintptr_t& return_rip)
|
||||||
|
{
|
||||||
|
ASSERT(signal >= _SIGMIN && signal <= _SIGMAX);
|
||||||
|
ASSERT(&Thread::current() == this);
|
||||||
|
|
||||||
|
// Skip masked (ignored) signals
|
||||||
|
if (m_signal_mask & (1ull << signal))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_signal_handlers[signal])
|
||||||
|
{
|
||||||
|
asm volatile("cli");
|
||||||
|
write_to_stack(return_rsp, return_rip);
|
||||||
|
write_to_stack(return_rsp, signal);
|
||||||
|
write_to_stack(return_rsp, m_signal_handlers[signal]);
|
||||||
|
return_rip = (uintptr_t)signal_trampoline;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (signal)
|
||||||
|
{
|
||||||
|
// Abnormal termination of the process with additional actions.
|
||||||
|
case SIGABRT:
|
||||||
|
case SIGBUS:
|
||||||
|
case SIGFPE:
|
||||||
|
case SIGILL:
|
||||||
|
case SIGQUIT:
|
||||||
|
case SIGSEGV:
|
||||||
|
case SIGSYS:
|
||||||
|
case SIGTRAP:
|
||||||
|
case SIGXCPU:
|
||||||
|
case SIGXFSZ:
|
||||||
|
// TODO: additional actions
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
// Abnormal termination of the process
|
||||||
|
case SIGALRM:
|
||||||
|
case SIGHUP:
|
||||||
|
case SIGINT:
|
||||||
|
case SIGKILL:
|
||||||
|
case SIGPIPE:
|
||||||
|
case SIGTERM:
|
||||||
|
case SIGUSR1:
|
||||||
|
case SIGUSR2:
|
||||||
|
case SIGPOLL:
|
||||||
|
case SIGPROF:
|
||||||
|
case SIGVTALRM:
|
||||||
|
{
|
||||||
|
auto message = BAN::String::formatted("killed by signal {}\n", signal);
|
||||||
|
(void)process().tty().write(0, message.data(), message.size());
|
||||||
|
process().exit(128 + signal);
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore the signal
|
||||||
|
case SIGCHLD:
|
||||||
|
case SIGURG:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Stop the process:
|
||||||
|
case SIGTSTP:
|
||||||
|
case SIGTTIN:
|
||||||
|
case SIGTTOU:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
|
// Continue the process, if it is stopped; otherwise, ignore the signal.
|
||||||
|
case SIGCONT:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("cli");
|
||||||
|
if (!m_signal_queue.empty() && m_signal_queue.front() == signal)
|
||||||
|
m_signal_queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::validate_stack() const
|
void Thread::validate_stack() const
|
||||||
{
|
{
|
||||||
if (stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size())
|
if (stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size())
|
||||||
|
|
Loading…
Reference in New Issue