Skip to content

Commit

Permalink
Some improvements to signals.
Browse files Browse the repository at this point in the history
- Add sigprocmask() and sigpending().
- Forked children inherit signal dispositions and masks.
- Exec clears signal dispositions and masks.
  • Loading branch information
awesomekling committed Nov 10, 2018
1 parent c97a586 commit 6a0a2c9
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 4 deletions.
39 changes: 37 additions & 2 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ int Process::sys$gethostname(char* buffer, size_t size)
Process* Process::fork(RegisterDump& regs)
{
auto* child = new Process(String(m_name), m_uid, m_gid, m_pid, m_ring, m_cwd.copyRef(), m_executable.copyRef(), m_tty, this);
if (!child)
return nullptr;

memcpy(child->m_signal_action_data, m_signal_action_data, sizeof(m_signal_action_data));
child->m_signal_mask = m_signal_mask;
#ifdef FORK_DEBUG
dbgprintf("fork: child=%p\n", child);
#endif
Expand Down Expand Up @@ -365,6 +370,9 @@ int Process::do_exec(const String& path, Vector<String>&& arguments, Vector<Stri
}
}

memset(m_signal_action_data, 0, sizeof(m_signal_action_data));
m_signal_mask = 0xffffffff;

InterruptDisabler disabler;
Scheduler::prepare_to_modify_tss(*this);

Expand Down Expand Up @@ -737,13 +745,13 @@ void Process::send_signal(byte signal, Process* sender)

bool Process::has_unmasked_pending_signals() const
{
return m_pending_signals & ~m_signal_mask;
return m_pending_signals & m_signal_mask;
}

void Process::dispatch_one_pending_signal()
{
ASSERT_INTERRUPTS_DISABLED();
dword signal_candidates = m_pending_signals & ~m_signal_mask;
dword signal_candidates = m_pending_signals & m_signal_mask;
ASSERT(signal_candidates);

byte signal = 0;
Expand Down Expand Up @@ -1470,6 +1478,33 @@ Unix::sighandler_t Process::sys$signal(int signum, Unix::sighandler_t handler)
return nullptr;
}

int Process::sys$sigprocmask(int how, const Unix::sigset_t* set, Unix::sigset_t* old_set)
{
VALIDATE_USER_READ(set, sizeof(Unix::sigset_t));
if (old_set)
VALIDATE_USER_READ(old_set, sizeof(Unix::sigset_t));
*old_set = m_signal_mask;
switch (how) {
case SIG_BLOCK:
m_signal_mask &= ~(*set);
break;
case SIG_UNBLOCK:
m_signal_mask |= *set;
break;
case SIG_SETMASK:
m_signal_mask = *set;
break;
}
return 0;
}

int Process::sys$sigpending(Unix::sigset_t* set)
{
VALIDATE_USER_READ(set, sizeof(Unix::sigset_t));
*set = m_pending_signals;
return 0;
}

int Process::sys$sigaction(int signum, const Unix::sigaction* act, Unix::sigaction* old_act)
{
// FIXME: Fail with -EINVAL if attepmting to change action for SIGKILL or SIGSTOP.
Expand Down
4 changes: 3 additions & 1 deletion Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ class Process : public InlineLinkedListNode<Process> {
int sys$dup(int oldfd);
int sys$dup2(int oldfd, int newfd);
int sys$sigaction(int signum, const Unix::sigaction* act, Unix::sigaction* old_act);
int sys$sigprocmask(int how, const Unix::sigset_t* set, Unix::sigset_t* old_set);
int sys$sigpending(Unix::sigset_t*);
int sys$getgroups(int size, gid_t*);
int sys$setgroups(size_t, const gid_t*);

Expand Down Expand Up @@ -247,7 +249,7 @@ class Process : public InlineLinkedListNode<Process> {
size_t m_max_open_file_descriptors { 16 };
SignalActionData m_signal_action_data[32];
dword m_pending_signals { 0 };
dword m_signal_mask { 0 };
dword m_signal_mask { 0xffffffff };

byte m_termination_status { 0 };
byte m_termination_signal { 0 };
Expand Down
2 changes: 2 additions & 0 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2,
current->sys$sigreturn();
ASSERT_NOT_REACHED();
return 0;
case Syscall::SC_sigprocmask:
return current->sys$sigprocmask((int)arg1, (const Unix::sigset_t*)arg2, (Unix::sigset_t*)arg3);
default:
kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
break;
Expand Down
2 changes: 2 additions & 0 deletions Kernel/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
__ENUMERATE_SYSCALL(getgroups) \
__ENUMERATE_SYSCALL(setgroups) \
__ENUMERATE_SYSCALL(sigreturn) \
__ENUMERATE_SYSCALL(sigprocmask) \
__ENUMERATE_SYSCALL(sigpending) \


#define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
Expand Down
13 changes: 12 additions & 1 deletion LibC/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,23 @@ int sigismember(const sigset_t* set, int sig)
return 0;
}

int sigprocmask(int how, const sigset_t* set, sigset_t* old_set)
{
int rc = Syscall::invoke(Syscall::SC_sigprocmask, (dword)how, (dword)set, (dword)old_set);
__RETURN_WITH_ERRNO(rc, rc, -1);
}

int sigpending(sigset_t* set)
{
int rc = Syscall::invoke(Syscall::SC_sigpending, (dword)set);
__RETURN_WITH_ERRNO(rc, rc, -1);
}

const char* sys_siglist[NSIG] = {
#undef __SIGNAL
#define __SIGNAL(a, b) b,
__ENUMERATE_ALL_SIGNALS
#undef __SIGNAL
};


}
2 changes: 2 additions & 0 deletions LibC/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ int sigfillset(sigset_t*);
int sigaddset(sigset_t*, int sig);
int sigdelset(sigset_t*, int sig);
int sigismember(const sigset_t*, int sig);
int sigprocmask(int how, const sigset_t* set, sigset_t* old_set);
int sigpending(sigset_t*);

#define NSIG 32
extern const char* sys_siglist[NSIG];
Expand Down
2 changes: 2 additions & 0 deletions LibC/sys/cdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
#undef __P
#define __P(a) a

#ifdef __cplusplus
extern "C" int main(int, char**);
#endif

0 comments on commit 6a0a2c9

Please sign in to comment.