forked from Bananymous/banan-os
Kernel: Userspace signal handlers are now called one at a time
I added a syscall for telling the kernel when signal execution has finished. We should send a random hash or id to the signal trampoline that we would include in the syscall, so validity of signal exit can be confirmed.
This commit is contained in:
parent
7391d91317
commit
adb14ba373
|
@ -46,6 +46,7 @@ set(KERNEL_SOURCES
|
||||||
kernel/Scheduler.cpp
|
kernel/Scheduler.cpp
|
||||||
kernel/Semaphore.cpp
|
kernel/Semaphore.cpp
|
||||||
kernel/Serial.cpp
|
kernel/Serial.cpp
|
||||||
|
kernel/Signal.cpp
|
||||||
kernel/SpinLock.cpp
|
kernel/SpinLock.cpp
|
||||||
kernel/SSP.cpp
|
kernel/SSP.cpp
|
||||||
kernel/Storage/ATABus.cpp
|
kernel/Storage/ATABus.cpp
|
||||||
|
|
|
@ -24,6 +24,9 @@ signal_trampoline:
|
||||||
movq 120(%rsp), %rax
|
movq 120(%rsp), %rax
|
||||||
call *%rax
|
call *%rax
|
||||||
|
|
||||||
|
movq 128(%rsp), %rdi
|
||||||
|
call signal_done
|
||||||
|
|
||||||
popq %r15
|
popq %r15
|
||||||
popq %r14
|
popq %r14
|
||||||
popq %r13
|
popq %r13
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace Kernel
|
||||||
void setup_exec();
|
void setup_exec();
|
||||||
|
|
||||||
bool has_signal_to_execute() const;
|
bool has_signal_to_execute() const;
|
||||||
|
void set_signal_done(int signal);
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <kernel/Syscall.h>
|
||||||
|
|
||||||
|
extern "C" __attribute__((section(".userspace")))
|
||||||
|
void signal_done(int signal)
|
||||||
|
{
|
||||||
|
Kernel::syscall(SYS_SIGNAL_DONE, signal);
|
||||||
|
}
|
|
@ -22,6 +22,12 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
Thread::current().set_in_syscall(true);
|
Thread::current().set_in_syscall(true);
|
||||||
|
|
||||||
|
if (syscall == SYS_SIGNAL_DONE)
|
||||||
|
{
|
||||||
|
Thread::current().set_signal_done((int)arg1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
asm volatile("sti");
|
asm volatile("sti");
|
||||||
|
|
||||||
(void)arg1;
|
(void)arg1;
|
||||||
|
@ -149,6 +155,9 @@ namespace Kernel
|
||||||
case SYS_SIGNAL:
|
case SYS_SIGNAL:
|
||||||
ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2);
|
ret = Process::current().sys_signal((int)arg1, (void (*)(int))arg2);
|
||||||
break;
|
break;
|
||||||
|
case SYS_SIGNAL_DONE:
|
||||||
|
// Handled above
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
default:
|
default:
|
||||||
dwarnln("Unknown syscall {}", syscall);
|
dwarnln("Unknown syscall {}", syscall);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -150,6 +150,19 @@ namespace Kernel
|
||||||
return !m_signal_queue.empty() && !m_handling_signal;
|
return !m_signal_queue.empty() && !m_handling_signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::set_signal_done(int signal)
|
||||||
|
{
|
||||||
|
ASSERT(!interrupts_enabled());
|
||||||
|
if (!m_handling_signal)
|
||||||
|
derrorln("set_signal_done called while not handling singal");
|
||||||
|
else if (m_signal_queue.empty())
|
||||||
|
derrorln("set_signal_done called and there are no signals in queue");
|
||||||
|
else if (m_signal_queue.front() != signal)
|
||||||
|
derrorln("set_signal_done called with wrong signal");
|
||||||
|
else
|
||||||
|
m_signal_queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::handle_next_signal()
|
void Thread::handle_next_signal()
|
||||||
{
|
{
|
||||||
ASSERT(!interrupts_enabled());
|
ASSERT(!interrupts_enabled());
|
||||||
|
@ -167,8 +180,6 @@ namespace Kernel
|
||||||
|
|
||||||
vaddr_t signal_handler = process().m_signal_handlers[signal];
|
vaddr_t signal_handler = process().m_signal_handlers[signal];
|
||||||
|
|
||||||
m_handling_signal = true;
|
|
||||||
|
|
||||||
// Skip masked and ignored signals
|
// Skip masked and ignored signals
|
||||||
if (m_signal_mask & (1ull << signal))
|
if (m_signal_mask & (1ull << signal))
|
||||||
;
|
;
|
||||||
|
@ -176,13 +187,15 @@ namespace Kernel
|
||||||
;
|
;
|
||||||
else if (signal_handler != (vaddr_t)SIG_DFL)
|
else if (signal_handler != (vaddr_t)SIG_DFL)
|
||||||
{
|
{
|
||||||
|
// call userspace signal handlers
|
||||||
|
// FIXME: signal trampoline should take a hash etc
|
||||||
|
// to only allow marking signals done from it
|
||||||
|
m_handling_signal = true;
|
||||||
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, signal_handler);
|
write_to_stack(return_rsp, signal_handler);
|
||||||
return_rip = (uintptr_t)signal_trampoline;
|
return_rip = (uintptr_t)signal_trampoline;
|
||||||
|
return;
|
||||||
// FIXME: we should only mark this signal as done when
|
|
||||||
// handler returns
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -241,7 +254,6 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
m_signal_queue.pop();
|
m_signal_queue.pop();
|
||||||
m_handling_signal = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::validate_stack() const
|
void Thread::validate_stack() const
|
||||||
|
|
|
@ -44,6 +44,7 @@ __BEGIN_DECLS
|
||||||
#define SYS_RAISE 37
|
#define SYS_RAISE 37
|
||||||
#define SYS_KILL 38
|
#define SYS_KILL 38
|
||||||
#define SYS_SIGNAL 39
|
#define SYS_SIGNAL 39
|
||||||
|
#define SYS_SIGNAL_DONE 40
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,9 @@ long syscall(long syscall, ...)
|
||||||
ret = Kernel::syscall(SYS_SIGNAL, signal, (uintptr_t)handler);
|
ret = Kernel::syscall(SYS_SIGNAL, signal, (uintptr_t)handler);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYS_SIGNAL_DONE:
|
||||||
|
// Should not be called by an user
|
||||||
|
// fall through
|
||||||
default:
|
default:
|
||||||
puts("LibC: Unhandeled syscall");
|
puts("LibC: Unhandeled syscall");
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
|
|
|
@ -281,6 +281,39 @@ int execute_command(BAN::Vector<BAN::String>& args)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (args.front() == "signal-test"sv)
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
if (signal(SIGSEGV, [](int) { printf("SIGSEGV\n"); }) == SIG_ERR)
|
||||||
|
{
|
||||||
|
perror("signal");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("child\n");
|
||||||
|
for (;;);
|
||||||
|
}
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
if (kill(pid, SIGSEGV) == -1)
|
||||||
|
{
|
||||||
|
perror("kill");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
if (kill(pid, SIGTERM) == -1)
|
||||||
|
{
|
||||||
|
perror("kill");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (args.front() == "cd"sv)
|
else if (args.front() == "cd"sv)
|
||||||
{
|
{
|
||||||
if (args.size() > 2)
|
if (args.size() > 2)
|
||||||
|
|
Loading…
Reference in New Issue