Skip to content

Commit

Permalink
Report that a process exited from a signal
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Aug 30, 2017
1 parent da3c873 commit 11f9110
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 38 deletions.
6 changes: 3 additions & 3 deletions fs/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ int tty_input(struct tty *tty, const char *input, size_t size) {
}

tty->canon_ready = true;
signal(tty, produced);
notify(tty, produced);
poll_wake_pollable(&tty->pl);
while (tty->canon_ready)
wait_for(tty, consumed);
Expand All @@ -156,7 +156,7 @@ int tty_input(struct tty *tty, const char *input, size_t size) {
size = sizeof(tty->buf) - 1 - tty->bufsize;
memcpy(tty->buf + tty->bufsize, input, size);
tty->bufsize += size;
signal(tty, produced);
notify(tty, produced);
poll_wake_pollable(&tty->pl);
}

Expand Down Expand Up @@ -189,7 +189,7 @@ static ssize_t tty_read(struct fd *fd, void *buf, size_t bufsize) {
tty->bufsize -= bufsize;
memmove(tty->buf, tty->buf + bufsize, tty->bufsize); // magic!
tty->canon_ready = false;
signal(tty, consumed);
notify(tty, consumed);

unlock(tty);
return bufsize;
Expand Down
2 changes: 1 addition & 1 deletion misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ typedef sdword_t int_t;
#define lock(thing) pthread_mutex_lock(&(thing)->lock)
#define unlock(thing) pthread_mutex_unlock(&(thing)->lock)
#define wait_for(thing, what) pthread_cond_wait(&(thing)->what, &(thing)->lock)
#define signal(thing, what) pthread_cond_broadcast(&(thing)->what)
#define notify(thing, what) pthread_cond_broadcast(&(thing)->what)

#endif
1 change: 1 addition & 0 deletions sys/calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dword_t sys_vfork();
int sys_execve(const char *file, char *const argv[], char *const envp[]);
dword_t _sys_execve(addr_t file, addr_t argv, addr_t envp);
dword_t sys_exit(dword_t status);
noreturn void do_exit(int status);
dword_t sys_exit_group(dword_t status);
dword_t sys_wait4(dword_t pid, addr_t status_addr, dword_t options, addr_t rusage_addr);
dword_t sys_waitpid(dword_t pid, addr_t status_addr, dword_t options);
Expand Down
18 changes: 9 additions & 9 deletions sys/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ noreturn void do_exit(int status) {
if (current->pid == 1) {
exit(status >> 8);
}
pthread_mutex_lock(&current->parent->lock);
lock(current->parent);
current->exit_code = status;
current->zombie = true;
pthread_cond_broadcast(&current->parent->child_exit);
pthread_mutex_unlock(&current->parent->lock);
notify(current->parent, child_exit);
unlock(current->parent);

pthread_mutex_lock(&current->lock);
pthread_cond_broadcast(&current->vfork_done);
pthread_mutex_unlock(&current->lock);
lock(current);
notify(current, vfork_done);
unlock(current);

pthread_exit(NULL);
}
Expand Down Expand Up @@ -69,7 +69,7 @@ dword_t sys_wait4(dword_t pid, addr_t status_addr, dword_t options, addr_t rusag
return _ESRCH;
}

pthread_mutex_lock(&current->lock);
lock(current);

retry:
if (pid == (dword_t) -1) {
Expand All @@ -87,11 +87,11 @@ dword_t sys_wait4(dword_t pid, addr_t status_addr, dword_t options, addr_t rusag
}

// no matching zombie found, wait for one
pthread_cond_wait(&current->child_exit, &current->lock);
wait_for(current, child_exit);
goto retry;

found_zombie:
pthread_mutex_unlock(&current->lock);
unlock(current);
return pid;
}

Expand Down
5 changes: 3 additions & 2 deletions sys/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ struct process {
struct fd *files[MAX_FD];

struct sigaction_ sigactions[NUM_SIGS];
sigset_t_ mask;
sigset_t_ queued;
sigset_t_ blocked;
sigset_t_ queued; // where blocked signals go when they're sent
sigset_t_ pending;

struct process *parent;
struct list children;
Expand Down
69 changes: 48 additions & 21 deletions sys/signal.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "debug.h"
#include <signal.h>
#include "sys/calls.h"
#include "sys/signal.h"
#include "sys/vdso.h"
Expand All @@ -7,20 +8,29 @@ int xsave_extra = 0;
int fxsave_extra = 0;

void send_signal(struct process *proc, int sig) {
if (proc->sigactions[sig].handler == SIG_IGN_)
return;
if (proc->sigactions[sig].handler == SIG_DFL_)
sys_exit(0);
if (proc->mask & (1 << sig)) {
proc->queued |= (1 << sig);
return;
lock(proc);
if (proc->sigactions[sig].handler != SIG_IGN_) {
if (proc->blocked & (1 << sig)) {
proc->queued |= (1 << sig);
unlock(proc);
} else {
proc->pending |= (1 << sig);
unlock(proc);
pthread_kill(proc->thread, SIGUSR1);
}
}
}

static void receive_signal(int sig) {
if (current->sigactions[sig].handler == SIG_DFL_) {
do_exit(sig);
}

// setup the frame
struct sigframe_ frame = {};
frame.sig = sig;

struct cpu_state *cpu = &proc->cpu;
struct cpu_state *cpu = &current->cpu;
frame.sc.ax = cpu->eax;
frame.sc.bx = cpu->ebx;
frame.sc.cx = cpu->ecx;
Expand All @@ -40,15 +50,15 @@ void send_signal(struct process *proc, int sig) {
fprintf(stderr, "sigreturn not found in vdso, this should never happen\n");
abort();
}
frame.pretcode = proc->vdso + sigreturn_addr;
frame.pretcode = current->vdso + sigreturn_addr;
// for legacy purposes
frame.retcode.popmov = 0xb858;
frame.retcode.nr_sigreturn = 173; // rt_sigreturn
frame.retcode.int80 = 0x80cd;

// set up registers for signal handler
cpu->eax = sig;
cpu->eip = proc->sigactions[sig].handler;
cpu->eip = current->sigactions[sig].handler;

dword_t sp = cpu->esp;
if (xsave_extra) {
Expand All @@ -66,7 +76,20 @@ void send_signal(struct process *proc, int sig) {

// install frame
// nothing we can do if this fails
// TODO do something other than nothing, like printk maybe
(void) user_put(sp, frame);

current->queued &= ~(1 << sig);
}

void receive_signals() {
lock(current);
if (current->pending) {
for (int sig = 0; sig < NUM_SIGS; sig++)
if (current->pending & (1 << sig))
receive_signal(sig);
}
unlock(current);
}

static int do_sigaction(int sig, const struct sigaction_ *action, struct sigaction_ *oldaction) {
Expand All @@ -75,10 +98,12 @@ static int do_sigaction(int sig, const struct sigaction_ *action, struct sigacti
if (sig == SIGKILL_ || sig == SIGSTOP_)
return _EINVAL;

lock(current);
if (oldaction)
*oldaction = current->sigactions[sig];
if (action)
current->sigactions[sig] = *action;
unlock(current);
return 0;
}

Expand Down Expand Up @@ -117,23 +142,25 @@ dword_t sys_rt_sigprocmask(dword_t how, addr_t set_addr, addr_t oldset_addr, dwo
sigset_t_ set;
if (user_get(set_addr, set))
return _EFAULT;
sigset_t_ oldset = current->mask;
sigset_t_ oldset = current->blocked;

lock(current);
if (how == SIG_BLOCK_)
current->mask |= set;
current->blocked |= set;
else if (how == SIG_UNBLOCK_)
current->mask &= ~set;
current->blocked &= ~set;
else if (how == SIG_SETMASK_)
current->mask = set;
else
current->blocked = set;
else {
unlock(current);
return _EINVAL;
}

sigset_t_ pending = current->queued & oldset & ~current->mask;
if (pending)
for (int sig = 0; sig < NUM_SIGS; sig++)
if (pending & (1 << sig))
send_signal(current, sig);
current->queued &= ~pending;
// transfer unblocked signals from queued to pending
sigset_t_ unblocked = oldset & ~current->blocked;
current->pending |= current->queued & unblocked;
current->queued &= ~unblocked;
unlock(current);

if (oldset_addr != 0)
if (user_put(oldset_addr, oldset))
Expand Down
1 change: 1 addition & 0 deletions sys/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct sigaction_ {

struct process;
void send_signal(struct process *proc, int sig);
void receive_signals();

dword_t sys_rt_sigaction(dword_t signum, addr_t action_addr, addr_t oldaction_addr, dword_t sigset_size);
dword_t sys_sigaction(dword_t signum, addr_t action_addr, addr_t oldaction_addr);
Expand Down
4 changes: 2 additions & 2 deletions util/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ size_t buf_read(struct buffer *buf, char *str, size_t len, int flags) {
if (buf->start >= buf->capacity)
buf->start -= buf->capacity;
buf->unread -= len;
signal(buf, changed);
notify(buf, changed);
unlock(buf);
return len;
}
Expand All @@ -77,7 +77,7 @@ size_t buf_write(struct buffer *buf, char *str, size_t len, int flags) {
memcpy(buf->data, str + len1, len - len1);

buf->unread += len;
signal(buf, changed);
notify(buf, changed);
unlock(buf);
return len;
}
Expand Down
5 changes: 5 additions & 0 deletions xX_main_Xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "sys/calls.h"
#include "fs/tty.h"

Expand Down Expand Up @@ -36,6 +37,10 @@ static inline int xX_main_Xx(int argc, char *const argv[]) {
}
mount_root(root_realpath);

struct sigaction sa;
sa.sa_handler = (void (*)(int)) receive_signals;
sigaction(SIGUSR1, &sa, NULL);

// make a process
current = process_create();
mem_init(&curmem);
Expand Down

0 comments on commit 11f9110

Please sign in to comment.