Kernel: Signals are not queued anymore

Posix doesn't require signal queing if you don't use sigqueue() which
we don't support. Process also has its own pending signal mask.
This commit is contained in:
Bananymous
2023-07-29 16:54:31 +03:00
parent 00f1f30a08
commit 879706e6e9
5 changed files with 61 additions and 35 deletions

View File

@@ -845,14 +845,14 @@ namespace Kernel
return Process::current().sys_raise(signal);
LockGuard process_guard(s_process_lock);
CriticalScope _;
for (auto* process : s_processes)
{
if (process->pid() == pid)
{
if (signal)
process->m_threads.front()->queue_signal(signal);
if (signal == 0)
return 0;
CriticalScope _;
process->m_signal_pending_mask |= 1ull << signal;
return 0;
}
}
@@ -864,12 +864,19 @@ namespace Kernel
{
if (signal < _SIGMIN || signal > _SIGMAX)
return BAN::Error::from_errno(EINVAL);
ASSERT(m_threads.size() == 1);
ASSERT(this == &Process::current());
CriticalScope _;
// FIXME: support raise with signal blocked
Thread& current = Thread::current();
current.queue_signal(signal);
current.handle_next_signal();
return 0;
if (current.add_signal(signal))
{
current.handle_signal(signal);
return 0;
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgid)

View File

@@ -248,7 +248,7 @@ namespace Kernel
start_thread(current->rsp(), current->rip());
case Thread::State::Executing:
while (current->has_signal_to_execute() && current->state() == Thread::State::Executing)
current->handle_next_signal();
current->handle_signal();
// fall through
case Thread::State::Terminating:
continue_thread(current->rsp(), current->rip());

View File

@@ -183,7 +183,7 @@ namespace Kernel
// Setup stack for returning
{
// FIXME: don't use PageTableScope
PageTableScope _(m_process->page_table());
PageTableScope _(process().page_table());
write_to_stack(m_rsp, this);
write_to_stack(m_rsp, &Thread::on_exit);
write_to_stack(m_rsp, nullptr);
@@ -204,12 +204,13 @@ namespace Kernel
m_rsp = stack_base() + stack_size();
m_rip = (uintptr_t)entry;
m_signal_mask = ~0ull;
m_signal_pending_mask = 0;
m_signal_block_mask = ~0ull;
// Setup stack for returning
{
// FIXME: don't use PageTableScope
PageTableScope _(m_process->page_table());
PageTableScope _(process().page_table());
write_to_stack(m_rsp, this);
write_to_stack(m_rsp, &Thread::on_exit);
write_to_stack(m_rsp, m_process);
@@ -218,7 +219,10 @@ namespace Kernel
bool Thread::has_signal_to_execute() const
{
return !m_signal_queue.empty() && !m_handling_signal;
if (!m_process || m_handling_signal)
return false;
uint64_t full_pending_mask = m_signal_pending_mask | m_process->m_signal_pending_mask;
return full_pending_mask & ~m_signal_block_mask;
}
void Thread::set_signal_done(int signal)
@@ -232,26 +236,40 @@ namespace Kernel
m_handling_signal = 0;
}
void Thread::handle_next_signal()
void Thread::handle_signal(int signal)
{
ASSERT(!interrupts_enabled());
ASSERT(!m_signal_queue.empty());
ASSERT(&Thread::current() == this);
ASSERT(is_userspace());
int signal = m_signal_queue.front();
ASSERT(signal >= _SIGMIN && signal <= _SIGMAX);
m_signal_queue.pop();
if (signal == 0)
{
uint64_t full_pending_mask = m_signal_pending_mask | process().m_signal_pending_mask;
for (signal = _SIGMIN; signal <= _SIGMAX; signal++)
{
uint64_t mask = 1ull << signal;
if ((full_pending_mask & mask) && !(m_signal_block_mask & mask))
break;
}
ASSERT(signal <= _SIGMAX);
}
else
{
uint64_t full_pending_mask = m_signal_pending_mask | process().m_signal_pending_mask;
uint64_t mask = 1ull << signal;
ASSERT(full_pending_mask & mask);
ASSERT(!(m_signal_block_mask & mask));
}
uintptr_t& return_rsp = this->return_rsp();
uintptr_t& return_rip = this->return_rip();
vaddr_t signal_handler = process().m_signal_handlers[signal];
// Skip masked and ignored signals
if (m_signal_mask & (1ull << signal))
;
else if (signal_handler == (vaddr_t)SIG_IGN)
m_signal_pending_mask &= ~(1ull << signal);
process().m_signal_pending_mask &= ~(1ull << signal);
if (signal_handler == (vaddr_t)SIG_IGN)
;
else if (signal_handler != (vaddr_t)SIG_DFL)
{
@@ -321,17 +339,18 @@ namespace Kernel
}
}
void Thread::queue_signal(int signal)
bool Thread::add_signal(int signal)
{
ASSERT(!interrupts_enabled());
if (m_signal_queue.full())
uint64_t mask = 1ull << signal;
if (!(m_signal_block_mask & mask))
{
dwarnln("Signal queue full");
return;
m_signal_pending_mask |= mask;
if (this != &Thread::current())
Scheduler::get().unblock_thread(tid());
return true;
}
m_signal_queue.push(signal);
if (this != &Thread::current())
Scheduler::get().unblock_thread(tid());
return false;
}
void Thread::validate_stack() const