kernel: Add sigaction
This commit is contained in:
parent
4c2e5da1c4
commit
2906476825
@ -37,9 +37,12 @@ uint16_t off_y;
|
|||||||
static int volatile draw_lock = 0;
|
static int volatile draw_lock = 0;
|
||||||
|
|
||||||
gfx_context_t * ctx;
|
gfx_context_t * ctx;
|
||||||
|
pthread_t thread;
|
||||||
|
|
||||||
void sigint_handler() {
|
void sigint_handler() {
|
||||||
should_exit = 1;
|
should_exit = 1;
|
||||||
|
pthread_join(thread, NULL);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void redraw_borders() {
|
void redraw_borders() {
|
||||||
@ -145,7 +148,6 @@ int main (int argc, char ** argv) {
|
|||||||
|
|
||||||
yutani_window_advertise_icon(yctx, wina, "Plasma", "plasma");
|
yutani_window_advertise_icon(yctx, wina, "Plasma", "plasma");
|
||||||
|
|
||||||
pthread_t thread;
|
|
||||||
pthread_create(&thread, NULL, draw_thread, NULL);
|
pthread_create(&thread, NULL, draw_thread, NULL);
|
||||||
|
|
||||||
signal(SIGINT, sigint_handler);
|
signal(SIGINT, sigint_handler);
|
||||||
|
@ -772,6 +772,7 @@ static void handle_syscall(pid_t pid, struct regs * r) {
|
|||||||
case SYS_GETTIMEOFDAY:
|
case SYS_GETTIMEOFDAY:
|
||||||
/* two output args */
|
/* two output args */
|
||||||
break;
|
break;
|
||||||
|
case SYS_SIGACTION: break;
|
||||||
/* These have no arguments: */
|
/* These have no arguments: */
|
||||||
case SYS_YIELD:
|
case SYS_YIELD:
|
||||||
case SYS_FORK:
|
case SYS_FORK:
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/signal_defs.h>
|
#include <sys/signal_defs.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
#include <kernel/arch/x86_64/pml.h>
|
#include <kernel/arch/x86_64/pml.h>
|
||||||
@ -73,6 +74,12 @@ typedef struct file_descriptors {
|
|||||||
spin_lock_t lock;
|
spin_lock_t lock;
|
||||||
} fd_table_t;
|
} fd_table_t;
|
||||||
|
|
||||||
|
struct signal_config {
|
||||||
|
uintptr_t handler;
|
||||||
|
sigset_t mask;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
#define PROC_FLAG_IS_TASKLET 0x01
|
#define PROC_FLAG_IS_TASKLET 0x01
|
||||||
#define PROC_FLAG_FINISHED 0x02
|
#define PROC_FLAG_FINISHED 0x02
|
||||||
#define PROC_FLAG_STARTED 0x04
|
#define PROC_FLAG_STARTED 0x04
|
||||||
@ -114,7 +121,6 @@ typedef struct process {
|
|||||||
list_t * wait_queue;
|
list_t * wait_queue;
|
||||||
list_t * shm_mappings;
|
list_t * shm_mappings;
|
||||||
list_t * node_waits;
|
list_t * node_waits;
|
||||||
list_t * signal_queue;
|
|
||||||
|
|
||||||
node_t sched_node;
|
node_t sched_node;
|
||||||
node_t sleep_node;
|
node_t sleep_node;
|
||||||
@ -125,12 +131,14 @@ typedef struct process {
|
|||||||
int awoken_index;
|
int awoken_index;
|
||||||
|
|
||||||
thread_t thread;
|
thread_t thread;
|
||||||
thread_t signal_state;
|
|
||||||
image_t image;
|
image_t image;
|
||||||
|
|
||||||
spin_lock_t sched_lock;
|
spin_lock_t sched_lock;
|
||||||
|
|
||||||
uintptr_t signals[NUMSIGNALS+1];
|
struct signal_config signals[NUMSIGNALS+1];
|
||||||
|
sigset_t blocked_signals;
|
||||||
|
sigset_t pending_signals;
|
||||||
|
sigset_t active_signals;
|
||||||
|
|
||||||
int supplementary_group_count;
|
int supplementary_group_count;
|
||||||
gid_t * supplementary_group_list;
|
gid_t * supplementary_group_list;
|
||||||
@ -273,5 +281,5 @@ extern void arch_enter_user(uintptr_t entrypoint, int argc, char * argv[], char
|
|||||||
__attribute__((noreturn))
|
__attribute__((noreturn))
|
||||||
extern void arch_enter_signal_handler(uintptr_t,int,struct regs*);
|
extern void arch_enter_signal_handler(uintptr_t,int,struct regs*);
|
||||||
extern void arch_wakeup_others(void);
|
extern void arch_wakeup_others(void);
|
||||||
extern void arch_return_from_signal_handler(struct regs *r);
|
extern int arch_return_from_signal_handler(struct regs *r);
|
||||||
|
|
||||||
|
@ -16,5 +16,7 @@ typedef int sig_atomic_t;
|
|||||||
|
|
||||||
extern sighandler_t signal(int signum, sighandler_t handler);
|
extern sighandler_t signal(int signum, sighandler_t handler);
|
||||||
extern int raise(int sig);
|
extern int raise(int sig);
|
||||||
|
extern int sigaction(int signum, struct sigaction *act, struct sigaction *oldact);
|
||||||
|
extern int sigemptyset(sigset_t *);
|
||||||
|
|
||||||
_End_C_Header
|
_End_C_Header
|
||||||
|
@ -16,6 +16,9 @@ _Begin_C_Header
|
|||||||
|
|
||||||
#define SA_NOCLDSTOP 1
|
#define SA_NOCLDSTOP 1
|
||||||
#define SA_SIGINFO 2
|
#define SA_SIGINFO 2
|
||||||
|
#define SA_NODEFER 4
|
||||||
|
#define SA_RESETHAND 8
|
||||||
|
#define SA_RESTART 16
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define SIG_SETMASK 0
|
#define SIG_SETMASK 0
|
||||||
|
@ -73,3 +73,4 @@
|
|||||||
#define SYS_SETGROUPS 70
|
#define SYS_SETGROUPS 70
|
||||||
#define SYS_TIMES 71
|
#define SYS_TIMES 71
|
||||||
#define SYS_SETTIMEOFDAY 72
|
#define SYS_SETTIMEOFDAY 72
|
||||||
|
#define SYS_SIGACTION 73
|
||||||
|
@ -69,7 +69,7 @@ static void _kill_it(uintptr_t addr, const char * action, const char * desc, siz
|
|||||||
stack += sizeof(type); \
|
stack += sizeof(type); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void arch_return_from_signal_handler(struct regs *r) {
|
int arch_return_from_signal_handler(struct regs *r) {
|
||||||
uintptr_t spsr;
|
uintptr_t spsr;
|
||||||
uintptr_t sp = r->user_sp;
|
uintptr_t sp = r->user_sp;
|
||||||
|
|
||||||
@ -81,6 +81,10 @@ void arch_return_from_signal_handler(struct regs *r) {
|
|||||||
}
|
}
|
||||||
arch_restore_floating((process_t*)this_core->current_process);
|
arch_restore_floating((process_t*)this_core->current_process);
|
||||||
|
|
||||||
|
POP(sp, sigset_t, this_core->current_process->blocked_signals);
|
||||||
|
long originalSignal;
|
||||||
|
POP(sp, long, originalSignal);
|
||||||
|
|
||||||
/* Interrupt system call status */
|
/* Interrupt system call status */
|
||||||
POP(sp, long, this_core->current_process->interrupted_system_call);
|
POP(sp, long, this_core->current_process->interrupted_system_call);
|
||||||
|
|
||||||
@ -95,6 +99,7 @@ void arch_return_from_signal_handler(struct regs *r) {
|
|||||||
POP(sp, struct regs, *r);
|
POP(sp, struct regs, *r);
|
||||||
|
|
||||||
asm volatile ("msr SP_EL0, %0" :: "r"(r->user_sp));
|
asm volatile ("msr SP_EL0, %0" :: "r"(r->user_sp));
|
||||||
|
return originalSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,6 +131,12 @@ void arch_enter_signal_handler(uintptr_t entrypoint, int signum, struct regs *r)
|
|||||||
PUSH(sp, long, this_core->current_process->interrupted_system_call);
|
PUSH(sp, long, this_core->current_process->interrupted_system_call);
|
||||||
this_core->current_process->interrupted_system_call = 0;
|
this_core->current_process->interrupted_system_call = 0;
|
||||||
|
|
||||||
|
PUSH(sp, long, signum);
|
||||||
|
PUSH(sp, sigset_t, this_core->current_process->blocked_signals);
|
||||||
|
|
||||||
|
struct signal_config * config = (struct signal_config*)&this_core->current_process->signals[signum];
|
||||||
|
this_core->current_process->blocked_signals |= config->mask | (1 << signum);
|
||||||
|
|
||||||
/* Save floating point */
|
/* Save floating point */
|
||||||
arch_save_floating((process_t*)this_core->current_process);
|
arch_save_floating((process_t*)this_core->current_process);
|
||||||
for (int i = 0; i < 64; ++i) {
|
for (int i = 0; i < 64; ++i) {
|
||||||
|
@ -68,7 +68,7 @@ static void _kill_it(void) {
|
|||||||
stack += sizeof(type); \
|
stack += sizeof(type); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void arch_return_from_signal_handler(struct regs *r) {
|
int arch_return_from_signal_handler(struct regs *r) {
|
||||||
|
|
||||||
for (int i = 0; i < 64; ++i) {
|
for (int i = 0; i < 64; ++i) {
|
||||||
POP(r->rsp, uint64_t, this_core->current_process->thread.fp_regs[63-i]);
|
POP(r->rsp, uint64_t, this_core->current_process->thread.fp_regs[63-i]);
|
||||||
@ -76,6 +76,10 @@ void arch_return_from_signal_handler(struct regs *r) {
|
|||||||
|
|
||||||
arch_restore_floating((process_t*)this_core->current_process);
|
arch_restore_floating((process_t*)this_core->current_process);
|
||||||
|
|
||||||
|
POP(r->rsp, sigset_t, this_core->current_process->blocked_signals);
|
||||||
|
long originalSignal;
|
||||||
|
POP(r->rsp, long, originalSignal);
|
||||||
|
|
||||||
POP(r->rsp, long, this_core->current_process->interrupted_system_call);
|
POP(r->rsp, long, this_core->current_process->interrupted_system_call);
|
||||||
|
|
||||||
struct regs out;
|
struct regs out;
|
||||||
@ -91,6 +95,7 @@ void arch_return_from_signal_handler(struct regs *r) {
|
|||||||
R(rsp);
|
R(rsp);
|
||||||
|
|
||||||
r->rflags = (out.rflags & 0xcd5) | (1 << 21) | (1 << 9) | ((r->rflags & (1 << 8)) ? (1 << 8) : 0);
|
r->rflags = (out.rflags & 0xcd5) | (1 << 21) | (1 << 9) | ((r->rflags & (1 << 8)) ? (1 << 8) : 0);
|
||||||
|
return originalSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,6 +125,12 @@ void arch_enter_signal_handler(uintptr_t entrypoint, int signum, struct regs *r)
|
|||||||
PUSH(ret.rsp, long, this_core->current_process->interrupted_system_call);
|
PUSH(ret.rsp, long, this_core->current_process->interrupted_system_call);
|
||||||
this_core->current_process->interrupted_system_call = 0;
|
this_core->current_process->interrupted_system_call = 0;
|
||||||
|
|
||||||
|
PUSH(ret.rsp, long, signum);
|
||||||
|
PUSH(ret.rsp, sigset_t, this_core->current_process->blocked_signals);
|
||||||
|
|
||||||
|
struct signal_config * config = (struct signal_config*)&this_core->current_process->signals[signum];
|
||||||
|
this_core->current_process->blocked_signals |= config->mask | (1 << signum);
|
||||||
|
|
||||||
arch_save_floating((process_t*)this_core->current_process);
|
arch_save_floating((process_t*)this_core->current_process);
|
||||||
for (int i = 0; i < 64; ++i) {
|
for (int i = 0; i < 64; ++i) {
|
||||||
PUSH(ret.rsp, uint64_t, this_core->current_process->thread.fp_regs[i]);
|
PUSH(ret.rsp, uint64_t, this_core->current_process->thread.fp_regs[i]);
|
||||||
|
@ -123,11 +123,10 @@ void switch_next(void) {
|
|||||||
mmu_set_directory(this_core->current_process->thread.page_directory->directory);
|
mmu_set_directory(this_core->current_process->thread.page_directory->directory);
|
||||||
arch_set_kernel_stack(this_core->current_process->image.stack);
|
arch_set_kernel_stack(this_core->current_process->image.stack);
|
||||||
|
|
||||||
if ((this_core->current_process->flags & PROC_FLAG_FINISHED) || (!this_core->current_process->signal_queue)) {
|
if (this_core->current_process->flags & PROC_FLAG_FINISHED) {
|
||||||
arch_fatal_prepare();
|
arch_fatal_prepare();
|
||||||
printf("Should not have this process...\n");
|
printf("Should not have this process...\n");
|
||||||
if (this_core->current_process->flags & PROC_FLAG_FINISHED) printf("It is marked finished.\n");
|
if (this_core->current_process->flags & PROC_FLAG_FINISHED) printf("It is marked finished.\n");
|
||||||
if (!this_core->current_process->signal_queue) printf("It doesn't have a signal queue.\n");
|
|
||||||
arch_dump_traceback();
|
arch_dump_traceback();
|
||||||
arch_fatal();
|
arch_fatal();
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
@ -356,7 +355,6 @@ process_t * spawn_kidle(int bsp) {
|
|||||||
* Can we make sure these are never referenced and not allocate them? */
|
* Can we make sure these are never referenced and not allocate them? */
|
||||||
idle->wait_queue = list_create("process wait queue (kidle)",idle);
|
idle->wait_queue = list_create("process wait queue (kidle)",idle);
|
||||||
idle->shm_mappings = list_create("process shm mappings (kidle)",idle);
|
idle->shm_mappings = list_create("process shm mappings (kidle)",idle);
|
||||||
idle->signal_queue = list_create("process signal queue (kidle)",idle);
|
|
||||||
gettimeofday(&idle->start, NULL);
|
gettimeofday(&idle->start, NULL);
|
||||||
idle->thread.page_directory = malloc(sizeof(page_directory_t));
|
idle->thread.page_directory = malloc(sizeof(page_directory_t));
|
||||||
idle->thread.page_directory->refcount = 1;
|
idle->thread.page_directory->refcount = 1;
|
||||||
@ -406,7 +404,6 @@ process_t * spawn_init(void) {
|
|||||||
init->flags = PROC_FLAG_STARTED | PROC_FLAG_RUNNING;
|
init->flags = PROC_FLAG_STARTED | PROC_FLAG_RUNNING;
|
||||||
init->wait_queue = list_create("process wait queue (init)", init);
|
init->wait_queue = list_create("process wait queue (init)", init);
|
||||||
init->shm_mappings = list_create("process shm mapping (init)", init);
|
init->shm_mappings = list_create("process shm mapping (init)", init);
|
||||||
init->signal_queue = list_create("process signal queue (init)", init);
|
|
||||||
|
|
||||||
init->sched_node.prev = NULL;
|
init->sched_node.prev = NULL;
|
||||||
init->sched_node.next = NULL;
|
init->sched_node.next = NULL;
|
||||||
@ -495,7 +492,6 @@ process_t * spawn_process(volatile process_t * parent, int flags) {
|
|||||||
|
|
||||||
proc->wait_queue = list_create("process wait queue",proc);
|
proc->wait_queue = list_create("process wait queue",proc);
|
||||||
proc->shm_mappings = list_create("process shm mappings",proc);
|
proc->shm_mappings = list_create("process shm mappings",proc);
|
||||||
proc->signal_queue = list_create("process signal queue",proc);
|
|
||||||
|
|
||||||
proc->sched_node.value = proc;
|
proc->sched_node.value = proc;
|
||||||
proc->sleep_node.value = proc;
|
proc->sleep_node.value = proc;
|
||||||
@ -1216,8 +1212,6 @@ void task_exit(int retval) {
|
|||||||
/* free whatever we can */
|
/* free whatever we can */
|
||||||
list_free(this_core->current_process->wait_queue);
|
list_free(this_core->current_process->wait_queue);
|
||||||
free(this_core->current_process->wait_queue);
|
free(this_core->current_process->wait_queue);
|
||||||
list_free(this_core->current_process->signal_queue);
|
|
||||||
free(this_core->current_process->signal_queue);
|
|
||||||
free(this_core->current_process->wd_name);
|
free(this_core->current_process->wd_name);
|
||||||
if (this_core->current_process->node_waits) {
|
if (this_core->current_process->node_waits) {
|
||||||
list_free(this_core->current_process->node_waits);
|
list_free(this_core->current_process->node_waits);
|
||||||
@ -1417,7 +1411,6 @@ process_t * spawn_worker_thread(void (*entrypoint)(void * argp), const char * na
|
|||||||
|
|
||||||
proc->wait_queue = list_create("worker thread wait queue",proc);
|
proc->wait_queue = list_create("worker thread wait queue",proc);
|
||||||
proc->shm_mappings = list_create("worker thread shm mappings",proc);
|
proc->shm_mappings = list_create("worker thread shm mappings",proc);
|
||||||
proc->signal_queue = list_create("worker thread signal queue",proc);
|
|
||||||
|
|
||||||
proc->sched_node.value = proc;
|
proc->sched_node.value = proc;
|
||||||
proc->sleep_node.value = proc;
|
proc->sleep_node.value = proc;
|
||||||
|
@ -91,11 +91,16 @@ static char sig_defaults[] = {
|
|||||||
*
|
*
|
||||||
* @param r Registers after restoration from signal return.
|
* @param r Registers after restoration from signal return.
|
||||||
*/
|
*/
|
||||||
static void maybe_restart_system_call(struct regs * r) {
|
static void maybe_restart_system_call(struct regs * r, int signum) {
|
||||||
if (this_core->current_process->interrupted_system_call && arch_syscall_number(r) == -ERESTARTSYS) {
|
if (this_core->current_process->interrupted_system_call && arch_syscall_number(r) == -ERESTARTSYS) {
|
||||||
arch_syscall_return(r, this_core->current_process->interrupted_system_call);
|
if (sig_defaults[signum] == SIG_DISP_Cont || (this_core->current_process->signals[signum].flags & SA_RESTART)) {
|
||||||
this_core->current_process->interrupted_system_call = 0;
|
arch_syscall_return(r, this_core->current_process->interrupted_system_call);
|
||||||
syscall_handler(r);
|
this_core->current_process->interrupted_system_call = 0;
|
||||||
|
syscall_handler(r);
|
||||||
|
} else {
|
||||||
|
this_core->current_process->interrupted_system_call = 0;
|
||||||
|
arch_syscall_return(r, -EINTR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,11 +124,8 @@ static void maybe_restart_system_call(struct regs * r) {
|
|||||||
* forward to @c arch_enter_signal_handler
|
* forward to @c arch_enter_signal_handler
|
||||||
* @returns 0 if another signal needs to be handled, 1 otherwise.
|
* @returns 0 if another signal needs to be handled, 1 otherwise.
|
||||||
*/
|
*/
|
||||||
int handle_signal(process_t * proc, signal_t * sig, struct regs *r) {
|
int handle_signal(process_t * proc, int signum, struct regs *r) {
|
||||||
uintptr_t signum = sig->signum;
|
struct signal_config config = proc->signals[signum];
|
||||||
free(sig);
|
|
||||||
|
|
||||||
uintptr_t handler = proc->signals[signum];
|
|
||||||
|
|
||||||
/* Are we being traced? */
|
/* Are we being traced? */
|
||||||
if (this_core->current_process->flags & PROC_FLAG_TRACE_SIGNALS) {
|
if (this_core->current_process->flags & PROC_FLAG_TRACE_SIGNALS) {
|
||||||
@ -138,7 +140,7 @@ int handle_signal(process_t * proc, signal_t * sig, struct regs *r) {
|
|||||||
goto _ignore_signal;
|
goto _ignore_signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handler) {
|
if (!config.handler) {
|
||||||
char dowhat = sig_defaults[signum];
|
char dowhat = sig_defaults[signum];
|
||||||
if (dowhat == SIG_DISP_Term || dowhat == SIG_DISP_Core) {
|
if (dowhat == SIG_DISP_Term || dowhat == SIG_DISP_Core) {
|
||||||
task_exit(((128 + signum) << 8) | signum);
|
task_exit(((128 + signum) << 8) | signum);
|
||||||
@ -155,7 +157,7 @@ int handle_signal(process_t * proc, signal_t * sig, struct regs *r) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
switch_task(0);
|
switch_task(0);
|
||||||
} while (!this_core->current_process->signal_queue->length);
|
} while (!(this_core->current_process->pending_signals & ~this_core->current_process->blocked_signals));
|
||||||
|
|
||||||
return 0; /* Return and handle another */
|
return 0; /* Return and handle another */
|
||||||
} else if (dowhat == SIG_DISP_Cont) {
|
} else if (dowhat == SIG_DISP_Cont) {
|
||||||
@ -166,19 +168,21 @@ int handle_signal(process_t * proc, signal_t * sig, struct regs *r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the handler value is 1 we treat it as IGN. */
|
/* If the handler value is 1 we treat it as IGN. */
|
||||||
if (handler == 1) goto _ignore_signal;
|
if (config.handler == 1) goto _ignore_signal;
|
||||||
|
|
||||||
proc->signals[signum] = 0;
|
if (config.flags & SA_RESETHAND) {
|
||||||
|
proc->signals[signum].handler = 0;
|
||||||
|
}
|
||||||
|
|
||||||
arch_enter_signal_handler(handler, signum, r);
|
arch_enter_signal_handler(config.handler, signum, r);
|
||||||
return 1; /* Should not be reachable */
|
return 1; /* Should not be reachable */
|
||||||
|
|
||||||
_ignore_signal:
|
_ignore_signal:
|
||||||
/* we still need to check if we need to restart something */
|
/* we still need to check if we need to restart something */
|
||||||
|
|
||||||
maybe_restart_system_call(r);
|
maybe_restart_system_call(r, signum);
|
||||||
|
|
||||||
return !this_core->current_process->signal_queue->length;
|
return !(this_core->current_process->pending_signals & ~this_core->current_process->blocked_signals);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,12 +228,19 @@ int send_signal(pid_t process, int signal, int force_root) {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!receiver->signals[signal] && !sig_defaults[signal]) {
|
if (!receiver->signals[signal].handler && !sig_defaults[signal]) {
|
||||||
/* If there is no handler for a signal and its default disposition is IGNORE,
|
/* If there is no handler for a signal and its default disposition is IGNORE,
|
||||||
* we don't even bother sending it, to avoid having to interrupt + restart system calls. */
|
* we don't even bother sending it, to avoid having to interrupt + restart system calls. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (receiver->blocked_signals & (1 << signal)) {
|
||||||
|
spin_lock(sig_lock);
|
||||||
|
receiver->pending_signals |= (1 << signal);
|
||||||
|
spin_unlock(sig_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sig_defaults[signal] == SIG_DISP_Cont) {
|
if (sig_defaults[signal] == SIG_DISP_Cont) {
|
||||||
/* XXX: I'm not sure this check is necessary? And the SUSPEND flag flip probably
|
/* XXX: I'm not sure this check is necessary? And the SUSPEND flag flip probably
|
||||||
* should be on the receiving end. */
|
* should be on the receiving end. */
|
||||||
@ -242,11 +253,8 @@ int send_signal(pid_t process, int signal, int force_root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Append signal to list */
|
/* Append signal to list */
|
||||||
signal_t * sig = malloc(sizeof(signal_t));
|
|
||||||
sig->signum = signal;
|
|
||||||
|
|
||||||
spin_lock(sig_lock);
|
spin_lock(sig_lock);
|
||||||
list_insert(receiver->signal_queue, sig);
|
receiver->pending_signals |= (1 << signal);
|
||||||
spin_unlock(sig_lock);
|
spin_unlock(sig_lock);
|
||||||
|
|
||||||
/* Informs any blocking events that the process has been interrupted
|
/* Informs any blocking events that the process has been interrupted
|
||||||
@ -311,20 +319,20 @@ int group_send_signal(pid_t group, int signal, int force_root) {
|
|||||||
*/
|
*/
|
||||||
void process_check_signals(struct regs * r) {
|
void process_check_signals(struct regs * r) {
|
||||||
spin_lock(sig_lock);
|
spin_lock(sig_lock);
|
||||||
if (this_core->current_process &&
|
if (this_core->current_process && !(this_core->current_process->flags & PROC_FLAG_FINISHED)) {
|
||||||
!(this_core->current_process->flags & PROC_FLAG_FINISHED) &&
|
/* Set an pending signals that were previously blocked */
|
||||||
this_core->current_process->signal_queue &&
|
sigset_t active_signals = this_core->current_process->pending_signals & ~this_core->current_process->blocked_signals;
|
||||||
this_core->current_process->signal_queue->length > 0) {
|
|
||||||
while (1) {
|
|
||||||
node_t * node = list_dequeue(this_core->current_process->signal_queue);
|
|
||||||
spin_unlock(sig_lock);
|
|
||||||
|
|
||||||
signal_t * sig = node->value;
|
int signal = 0;
|
||||||
free(node);
|
while (active_signals && signal <= NUMSIGNALS) {
|
||||||
|
if (active_signals & 1) {
|
||||||
if (handle_signal((process_t*)this_core->current_process,sig,r)) return;
|
this_core->current_process->pending_signals &= ~(1 << signal);
|
||||||
|
spin_unlock(sig_lock);
|
||||||
spin_lock(sig_lock);
|
if (handle_signal((process_t*)this_core->current_process, signal, r)) return;
|
||||||
|
spin_lock(sig_lock);
|
||||||
|
}
|
||||||
|
active_signals >>= 1;
|
||||||
|
signal++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(sig_lock);
|
spin_unlock(sig_lock);
|
||||||
@ -342,6 +350,9 @@ void process_check_signals(struct regs * r) {
|
|||||||
* then to @c maybe_restart_system_call to handle system call restarts.
|
* then to @c maybe_restart_system_call to handle system call restarts.
|
||||||
*/
|
*/
|
||||||
void return_from_signal_handler(struct regs *r) {
|
void return_from_signal_handler(struct regs *r) {
|
||||||
arch_return_from_signal_handler(r);
|
int signum = arch_return_from_signal_handler(r);
|
||||||
maybe_restart_system_call(r);
|
if (this_core->current_process->pending_signals & ~this_core->current_process->blocked_signals) {
|
||||||
|
process_check_signals(r);
|
||||||
|
}
|
||||||
|
maybe_restart_system_call(r,signum);
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
#include <syscall_nums.h>
|
#include <syscall_nums.h>
|
||||||
#include <kernel/printf.h>
|
#include <kernel/printf.h>
|
||||||
#include <kernel/process.h>
|
#include <kernel/process.h>
|
||||||
@ -947,11 +948,33 @@ long sys_signal(long signum, uintptr_t handler) {
|
|||||||
if (signum > NUMSIGNALS) {
|
if (signum > NUMSIGNALS) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
uintptr_t old = this_core->current_process->signals[signum];
|
uintptr_t old = this_core->current_process->signals[signum].handler;
|
||||||
this_core->current_process->signals[signum] = handler;
|
this_core->current_process->signals[signum].handler = handler;
|
||||||
|
this_core->current_process->signals[signum].flags = SA_RESTART;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long sys_sigaction(int signum, struct sigaction *act, struct sigaction *oldact) {
|
||||||
|
if (act) PTRCHECK(act,sizeof(struct sigaction),0);
|
||||||
|
if (oldact) PTRCHECK(oldact,sizeof(struct sigaction),0);
|
||||||
|
|
||||||
|
if (signum > NUMSIGNALS) return -EINVAL;
|
||||||
|
|
||||||
|
if (oldact) {
|
||||||
|
oldact->sa_handler = (_sig_func_ptr)this_core->current_process->signals[signum].handler;
|
||||||
|
oldact->sa_mask = this_core->current_process->signals[signum].mask;
|
||||||
|
oldact->sa_flags = this_core->current_process->signals[signum].flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (act) {
|
||||||
|
this_core->current_process->signals[signum].handler = (uintptr_t)act->sa_handler;
|
||||||
|
this_core->current_process->signals[signum].mask = act->sa_mask;
|
||||||
|
this_core->current_process->signals[signum].flags = act->sa_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
long sys_fswait(int c, int fds[]) {
|
long sys_fswait(int c, int fds[]) {
|
||||||
PTR_VALIDATE(fds);
|
PTR_VALIDATE(fds);
|
||||||
if (!fds) return -EFAULT;
|
if (!fds) return -EFAULT;
|
||||||
@ -1159,6 +1182,7 @@ static long (*syscalls[])() = {
|
|||||||
[SYS_TIMES] = sys_times,
|
[SYS_TIMES] = sys_times,
|
||||||
[SYS_PTRACE] = ptrace_handle,
|
[SYS_PTRACE] = ptrace_handle,
|
||||||
[SYS_SETTIMEOFDAY] = sys_settimeofday,
|
[SYS_SETTIMEOFDAY] = sys_settimeofday,
|
||||||
|
[SYS_SIGACTION] = sys_sigaction,
|
||||||
|
|
||||||
[SYS_SOCKET] = net_socket,
|
[SYS_SOCKET] = net_socket,
|
||||||
[SYS_SETSOCKOPT] = net_setsockopt,
|
[SYS_SETSOCKOPT] = net_setsockopt,
|
||||||
|
15
libc/signal/sigaction.c
Normal file
15
libc/signal/sigaction.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <sys/signal.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <syscall_nums.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
DEFN_SYSCALL3(sigaction, SYS_SIGACTION, int, struct sigaction*, struct sigaction*);
|
||||||
|
|
||||||
|
int sigaction(int signum, struct sigaction *act, struct sigaction *oldact) {
|
||||||
|
__sets_errno(syscall_sigaction(signum, act, oldact));
|
||||||
|
}
|
||||||
|
|
||||||
|
int sigemptyset(sigset_t * set) {
|
||||||
|
*set = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user