Orion
Barry Moving signal handlers into separate namespace 7ae31b0 (2 years, 7 months ago)diff --git a/task/schedule.c b/task/schedule.c
index 1c00576..527b9ec 100644
--- a/task/schedule.c
+++ b/task/schedule.c
@@ -103,6 +103,8 @@ Task *
pop_from_queue(TaskQueue *queue)
{
Task *head = queue->start;
+ if (!head)
+ return NULL;
queue->start = head->next;
if (!queue->start)
queue->end = NULL;
diff --git a/task/signal.c b/task/signal.c
index c80c279..fce04de 100644
--- a/task/signal.c
+++ b/task/signal.c
@@ -26,18 +26,25 @@ handle_signals(void)
}
}
+/* Send a signal to a task */
+void
+send_sig(Task *target, int sig)
+{
+ target->sigset |= (1 << (sig - 1));
+}
+
/* Send a signal to a thread */
int
tgkill(pid_t tgid, pid_t tid, int sig)
{
- if (sig < 0 || sig > 31)
+ if (sig < 0 || sig >= 32)
return -EINVAL;
Task *task = find_task(tid);
if (!task || task->tgid != tgid)
return -ESRCH;
if (sig)
- task->sigset |= (1 << (sig - 1));
+ send_sig(task, sig);
return 0;
}
@@ -46,7 +53,7 @@ tgkill(pid_t tgid, pid_t tid, int sig)
int
kill(pid_t pid, int sig)
{
- if (sig < 0 || sig > 31)
+ if (sig < 0 || sig >= 32)
return -EINVAL;
int sent = 0;
@@ -55,9 +62,54 @@ kill(pid_t pid, int sig)
if (task->tgid != pid)
continue;
if (sig)
- task->sigset |= (1 << (sig - 1));
+ send_sig(task, sig);
sent++;
}
return sent ? 0 : -ESRCH;
}
+
+/* Install a signal handler */
+sighandler_t
+signal(int signum, sighandler_t handler)
+{
+ if (signum < 0 || signum >= 32)
+ return (sighandler_t) -EINVAL;
+
+ if (!verify_access(handler, 8, PROT_EXEC))
+ return (sighandler_t) -EFAULT;
+
+ sighandler_t old = current->signals->sig_handler[signum];
+ current->signals->sig_handler[signum] = handler;
+ return old;
+}
+
+/* Examine and change blocked signals */
+int
+sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+ if (!verify_access(set, sizeof(sigset_t), PROT_READ))
+ return -EFAULT;
+ if (!verify_access(oldset, sizeof(sigset_t), PROT_WRITE))
+ return -EFAULT;
+
+ if (oldset)
+ *oldset = current->blockedSignals;
+
+ if (!set)
+ return 0;
+
+ switch (how) {
+ case SIG_BLOCK:
+ current->blockedSignals |= *set;
+ return 0;
+ case SIG_UNBLOCK:
+ current->blockedSignals &= ~*set;
+ return 0;
+ case SIG_SETMASK:
+ current->blockedSignals = *set;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/task/syscall.c b/task/syscall.c
index d43542d..30e1a7b 100644
--- a/task/syscall.c
+++ b/task/syscall.c
@@ -14,25 +14,27 @@
/* List of syscalls */
void *syscalls[] = {
/* Tasking */
- [SYSCALL_DBGPRINTF] = dbgprintf,
- [SYSCALL_CLONE] = clone,
- [SYSCALL_EXIT] = exit,
- [SYSCALL_GETPID] = getpid,
- [SYSCALL_GETUID] = getuid,
- [SYSCALL_SETUID] = setuid,
- [SYSCALL_GETEUID] = geteuid,
- [SYSCALL_SETEUID] = seteuid,
- [SYSCALL_GETGID] = getgid,
- [SYSCALL_SETGID] = setgid,
- [SYSCALL_GETEGID] = getegid,
- [SYSCALL_SETEGID] = setegid,
- [SYSCALL_EXECVE] = execve,
- [SYSCALL_WAITPID] = waitpid,
- [SYSCALL_TGKILL] = tgkill,
- [SYSCALL_KILL] = kill,
- [SYSCALL_TIME] = time,
- [SYSCALL_TIMES] = times,
- [SYSCALL_SLEEP] = sleep,
+ [SYSCALL_DBGPRINTF] = dbgprintf,
+ [SYSCALL_CLONE] = clone,
+ [SYSCALL_EXIT] = exit,
+ [SYSCALL_GETPID] = getpid,
+ [SYSCALL_GETUID] = getuid,
+ [SYSCALL_SETUID] = setuid,
+ [SYSCALL_GETEUID] = geteuid,
+ [SYSCALL_SETEUID] = seteuid,
+ [SYSCALL_GETGID] = getgid,
+ [SYSCALL_SETGID] = setgid,
+ [SYSCALL_GETEGID] = getegid,
+ [SYSCALL_SETEGID] = setegid,
+ [SYSCALL_EXECVE] = execve,
+ [SYSCALL_WAITPID] = waitpid,
+ [SYSCALL_TGKILL] = tgkill,
+ [SYSCALL_KILL] = kill,
+ [SYSCALL_SIGNAL] = signal,
+ [SYSCALL_SIGPROCMASK] = sigprocmask,
+ [SYSCALL_TIME] = time,
+ [SYSCALL_TIMES] = times,
+ [SYSCALL_SLEEP] = sleep,
/* Files */
[SYSCALL_OPEN] = open,
diff --git a/task/task.c b/task/task.c
index 294b3cc..4657c4f 100644
--- a/task/task.c
+++ b/task/task.c
@@ -189,6 +189,15 @@ clone(int flags)
child->tls->back = file_get(parent->tls->back);
}
+ /* Signal handlers */
+ if (flags & CLONE_SIGHAND) {
+ child->signals = parent->signals;
+ child->signals->usage++;
+ } else {
+ child->signals = kmalloc(sizeof(SigHandlers));
+ child->signals->usage = 1;
+ }
+
/* Split tasks here */
uintptr_t esp, ebp, eip;
eip = read_eip();
@@ -232,10 +241,11 @@ terminate(void)
}
vm_destroy_region(current->stack);
- /* Clean unread IPC messages */
- /* TODO */
-
/* Clean signals */
+ if (--current->signals->usage == 0)
+ kfree(current->signals);
+
+ /* Clean unread IPC messages */
/* TODO */
/* Deschedule */
@@ -412,9 +422,11 @@ init_tasking(void)
current->vm->regions = NULL;
current->vm->usage = 1;
- /* Inter-Process Communication Namespace */
-
/* Signals Namespace */
+ current->signals = kmalloc(sizeof(SigHandlers));
+ current->signals->usage = 1;
+
+ /* Inter-Process Communication Namespace */
register_interrupt(0, timer_handler);
}
diff --git a/task/task.h b/task/task.h
index 228c3d8..4879c33 100644
--- a/task/task.h
+++ b/task/task.h
@@ -6,6 +6,7 @@
#include <sys/times.h>
#include <time.h>
#include <signal.h>
+#include "signal.h"
#include "../mem/paging.h"
#include "../mem/vm.h"
#include "../proc/proc.h"
@@ -31,7 +32,7 @@ enum States {
READY,
TERMINATED,
WAITING_FOR_CHILD,
- WAITING_FOR_READ,
+ WAITING_FOR_IO,
SLEEP,
};
@@ -63,7 +64,6 @@ struct Task {
TaskQueue waiting;
sigset_t sigset;
sigset_t blockedSignals;
- void (*sig_handler[32])(int);
/* Messages */
Message *msgQueue;
@@ -72,8 +72,8 @@ struct Task {
FileSystem *fs;
Files *files;
VirtualMemory *vm;
+ SigHandlers *signals;
// Messages *ipc;
-// Signals *signals;
};
extern Task *currentTask[];
@@ -122,6 +122,7 @@ int setegid(gid_t egid);
int isatty(int fd);
int execve(const char *file, char *argv[], char *envp[]);
+void send_sig(Task *target, int sig);
int tgkill(pid_t tgid, pid_t tid, int sig);
int kill(pid_t pid, int sig);