summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/arch/i386/mmu.c4
-rw-r--r--kernel/cpu/syscall.c8
-rw-r--r--kernel/fs/vfs.c12
-rw-r--r--kernel/fs/vfs.h1
-rw-r--r--kernel/includes/mmu.h2
-rw-r--r--kernel/includes/signal.h1
-rw-r--r--kernel/network/tcp.c2
-rw-r--r--kernel/queue.c7
-rw-r--r--kernel/sched/scheduler.c72
-rw-r--r--kernel/sched/scheduler.h4
-rwxr-xr-xmeta/userland.sh1
-rw-r--r--userland/libc/include/signal.h1
-rw-r--r--userland/minibox/Makefile2
-rw-r--r--userland/minibox/minibox.c2
-rw-r--r--userland/minibox/utilities/include.h1
-rw-r--r--userland/sh/sh.c54
-rw-r--r--userland/terminal/term.c16
17 files changed, 143 insertions, 47 deletions
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index 9b63a9a..7147c74 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -394,10 +394,10 @@ void *allocate_frame(Page *page, int rw, int is_kernel) {
return (void *)(frame_address * 0x1000);
}
-void mmu_free_address_range(void *ptr, size_t length) {
+void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd) {
size_t num_pages = (size_t)align_page((void *)length) / PAGE_SIZE;
for (size_t i = 0; i < num_pages; i++, ptr += PAGE_SIZE) {
- Page *page = get_page(ptr, NULL, PAGE_NO_ALLOCATE, 0);
+ Page *page = get_page(ptr, pd, PAGE_NO_ALLOCATE, 0);
if (!page) {
continue;
}
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 7734f4e..d47f858 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -87,9 +87,17 @@ void syscall_wait(int *status) {
return;
}
do {
+ current_task->is_halted = 1;
current_task->halts[WAIT_CHILD_HALT] = 1;
switch_task();
+ if (current_task->is_interrupted) {
+ break;
+ }
} while (current_task->halts[WAIT_CHILD_HALT]);
+ if (current_task->is_interrupted) {
+ current_task->is_interrupted = 0;
+ return;
+ }
if (status) {
*status = current_task->child_rc;
}
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 143dc9d..f2b763c 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -292,15 +292,15 @@ int vfs_open(const char *file, int flags, int mode) {
return vfs_create_fd(flags, mode, 0 /*is_tty*/, inode, NULL);
}
-int vfs_close(int fd) {
- vfs_fd_t *fd_ptr = get_vfs_fd(fd, NULL);
+int vfs_close_process(process_t *p, int fd) {
+ vfs_fd_t *fd_ptr = get_vfs_fd(fd, p);
if (NULL == fd_ptr) {
return -1;
}
assert(0 < fd_ptr->reference_count);
// Remove process reference
fd_ptr->reference_count--;
- current_task->file_descriptors[fd] = 0;
+ p->file_descriptors[fd] = 0;
// If no references left then free the contents
if (0 == fd_ptr->reference_count) {
if (fd_ptr->inode->close) {
@@ -312,6 +312,10 @@ int vfs_close(int fd) {
return 0;
}
+int vfs_close(int fd) {
+ return vfs_close_process(current_task, fd);
+}
+
int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset) {
if (!(vfs_fd->flags & O_READ)) {
return -EBADF;
@@ -380,7 +384,7 @@ vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset) {
return NULL;
}
assert(vfs_fd->inode);
- if(!vfs_fd->inode->get_vm_object) {
+ if (!vfs_fd->inode->get_vm_object) {
return NULL;
}
vfs_vm_object_t *r = vfs_fd->inode->get_vm_object(length, offset, vfs_fd);
diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h
index 74e5bf4..8e61e11 100644
--- a/kernel/fs/vfs.h
+++ b/kernel/fs/vfs.h
@@ -71,6 +71,7 @@ struct vfs_inode {
};
int vfs_close(int fd);
+int vfs_close_process(process_t *p, int fd);
vfs_fd_t *get_vfs_fd(int fd, process_t *p);
int vfs_open(const char *file, int flags, int mode);
void vfs_mount(char *path, vfs_inode_t *local_root);
diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h
index 1a3f7c9..9a27c5b 100644
--- a/kernel/includes/mmu.h
+++ b/kernel/includes/mmu.h
@@ -37,7 +37,7 @@ int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags,
void mmu_allocate_shared_kernel_region(void *rc, size_t n);
void *mmu_find_unallocated_virtual_range(void *addr, size_t length);
void mmu_remove_virtual_physical_address_mapping(void *ptr, size_t length);
-void mmu_free_address_range(void *ptr, size_t length);
+void mmu_free_address_range(void *ptr, size_t length, PageDirectory *pd);
void mmu_map_directories(void *dst, PageDirectory *d, void *src,
PageDirectory *s, size_t length);
u32 mmu_get_number_of_allocated_frames(void);
diff --git a/kernel/includes/signal.h b/kernel/includes/signal.h
index 7e9dd9c..b9ab4a7 100644
--- a/kernel/includes/signal.h
+++ b/kernel/includes/signal.h
@@ -6,6 +6,7 @@
#define SIGWINCH 2
#define SIGQUIT 3
#define SIG_IGN 4
+#define SIGTERM 15
typedef int sigset_t;
union sigval {
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index dd6e6a8..1a3641b 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -54,7 +54,7 @@ void tcp_wait_reply(struct TcpConnection *con) {
if (con->unhandled_packet) {
return;
}
- wait_for_interrupt();
+ switch_task();
}
}
diff --git a/kernel/queue.c b/kernel/queue.c
index d77af85..b1cf698 100644
--- a/kernel/queue.c
+++ b/kernel/queue.c
@@ -50,18 +50,14 @@ int queue_should_block(struct event_queue *q, int *is_empty) {
if (!list_get(&q->events, i, (void **)&ev)) {
break;
}
- kprintf("wait %d\n", i);
*is_empty = 0;
if (EVENT_TYPE_FD == ev->type) {
- kprintf("found fd: %d\n", ev->internal_id);
vfs_fd_t *fd = get_vfs_fd(ev->internal_id, q->p);
- kprintf("fd->inode->has_data: %x\n", fd->inode->has_data);
if (!fd) {
kprintf("queue: Invalid fd given\n");
continue;
}
if (fd->inode->has_data) {
- kprintf("no block\n");
return 0;
}
} else if (EVENT_TYPE_TCP_SOCKET == ev->type) {
@@ -69,10 +65,7 @@ int queue_should_block(struct event_queue *q, int *is_empty) {
assert(con);
assert(con->data_file);
if (con->data_file->has_data) {
- kprintf("has data\n");
return 0;
- } else {
- kprintf("blocking queue\n");
}
}
}
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index ebf2c32..7afd203 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -8,6 +8,7 @@
#include <fs/vfs.h>
#include <interrupts.h>
#include <queue.h>
+#include <signal.h>
// FIXME: Use the process_t struct instead or keep this contained in it.
TCB *current_task_TCB;
@@ -188,8 +189,7 @@ void tasking_init(void) {
}
int i = 0;
-void free_process(void) {
- process_t *p = current_task;
+void free_process(process_t *p) {
kprintf("pid: %x\n", p->pid);
kprintf("Exiting process: %s\n", p->program_name);
// free_process() will purge all contents such as allocated frames
@@ -199,53 +199,57 @@ void free_process(void) {
// Do a special free for shared memory which avoids labeling
// underlying frames as "unused".
for (int i = 0; i < 100; i++) {
- vfs_close(i);
- if (!current_task->maps[i]) {
+ vfs_close_process(p, i);
+ if (!p->maps[i]) {
continue;
}
- MemoryMap *m = current_task->maps[i];
+ MemoryMap *m = p->maps[i];
mmu_remove_virtual_physical_address_mapping(m->u_address, m->length);
}
// NOTE: Kernel stuff begins at 0x90000000
- mmu_free_address_range((void *)0x1000, 0x90000000);
+ mmu_free_address_range((void *)0x1000, 0x90000000, p->cr3);
list_free(&p->read_list);
list_free(&p->write_list);
list_free(&p->disconnect_list);
}
-void exit(int status) {
- assert(current_task->pid != 1);
- if (current_task->parent) {
- current_task->parent->halts[WAIT_CHILD_HALT] = 0;
- current_task->parent->child_rc = status;
+void exit_process(process_t *p, int status) {
+ assert(p->pid != 1);
+ if (p->parent) {
+ p->parent->halts[WAIT_CHILD_HALT] = 0;
+ p->parent->child_rc = status;
}
- process_t *new_task = current_task;
- for (; new_task == current_task;) {
+ process_t *new_task = p;
+ for (; new_task == p;) {
if (!new_task->next) {
new_task = ready_queue;
}
new_task = new_task->next;
}
- free_process();
+ free_process(p);
+ p->dead = 1;
// Remove current_task from list
for (process_t *tmp = ready_queue; tmp;) {
- if (tmp == current_task) // current_task is ready_queue(TODO:
- // Figure out whether this could even
- // happen)
+ if (tmp == p) // current_task is ready_queue(TODO:
+ // Figure out whether this could even
+ // happen)
{
- ready_queue = current_task->next;
+ ready_queue = p->next;
break;
}
- if (tmp->next == current_task) {
+ if (tmp->next == p) {
tmp->next = tmp->next->next;
break;
}
tmp = tmp->next;
}
- current_task->dead = 1;
+}
+
+void exit(int status) {
+ exit_process(current_task, status);
switch_task();
}
@@ -434,13 +438,20 @@ process_t *next_task(process_t *s) {
if (!c) {
c = ready_queue;
}
+ if (c->is_interrupted) {
+ break;
+ }
if (s == c) {
- wait_for_interrupt();
+ // wait_for_interrupt();
}
if (c->sleep_until > pit_num_ms()) {
continue;
}
- if (is_halted(c) || c->dead) {
+ if (c->dead) {
+ kprintf("dead process\n");
+ continue;
+ }
+ if (is_halted(c)) {
continue;
}
break;
@@ -448,6 +459,22 @@ process_t *next_task(process_t *s) {
return c;
}
+void signal_process(process_t *p, int sig) {
+ assert(sig < 32);
+ kprintf("sending signal to: %x\n", p);
+ if (!p->signal_handlers[sig]) {
+ if (SIGTERM == sig) {
+ kprintf("HAS NO SIGTERM\n");
+ exit_process(p, 1 /*TODO: what should the status be?*/);
+ } else {
+ // TODO: Should also exit proess(I think)
+ assert(0);
+ }
+ }
+ signal_t signal = {.handler_ip = (uintptr_t)p->signal_handlers[sig]};
+ process_push_signal(p, signal);
+}
+
int kill(pid_t pid, int sig) {
process_t *p = current_task;
p = p->next;
@@ -466,6 +493,7 @@ int kill(pid_t pid, int sig) {
if (p->pid != pid) {
return -ESRCH;
}
+ signal_process(p, sig);
return 0;
}
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index 175f3ce..fbaed3e 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -56,7 +56,7 @@ struct Process {
u32 pid;
char program_name[100];
char current_working_directory[MAX_PATH];
- void *signal_handlers[20];
+ void *signal_handlers[32];
void *interrupt_handler;
PageDirectory *cr3;
struct IpcMailbox ipc_mailbox;
@@ -96,6 +96,6 @@ struct Process {
bool get_task_from_pid(u32 pid, process_t **out);
int get_free_fd(process_t *p, int allocate);
-void free_process(void);
+void free_process(process_t *p);
void *get_free_virtual_memory(size_t length);
#endif
diff --git a/meta/userland.sh b/meta/userland.sh
index c8eb1ac..22e86ff 100755
--- a/meta/userland.sh
+++ b/meta/userland.sh
@@ -45,4 +45,5 @@ ln -s ./minibox ./yes
ln -s ./minibox ./echo
ln -s ./minibox ./wc
ln -s ./minibox ./ls
+ln -s ./minibox ./kill
cd ..
diff --git a/userland/libc/include/signal.h b/userland/libc/include/signal.h
index 621710b..2be081c 100644
--- a/userland/libc/include/signal.h
+++ b/userland/libc/include/signal.h
@@ -12,6 +12,7 @@
#define SIGBUS 8
#define SIGKILL 9
#define SIGFPE 10
+#define SIGTERM 15
typedef int pid_t;
typedef int sigset_t;
diff --git a/userland/minibox/Makefile b/userland/minibox/Makefile
index b2894c3..5d1e359 100644
--- a/userland/minibox/Makefile
+++ b/userland/minibox/Makefile
@@ -1,6 +1,6 @@
CC="i686-sb-gcc"
CFLAGS=-Wall -Wextra -pedantic -Wimplicit-fallthrough -g -O0
-OBJ=minibox.o utilities/cat.o utilities/echo.o utilities/yes.o utilities/minibox.o utilities/ascii.o utilities/wc.o utilities/init.o utilities/ls.o utilities/touch.o utilities/ed.o utilities/sh/sh.o utilities/sh/lexer.o utilities/sh/ast.o
+OBJ=minibox.o utilities/cat.o utilities/echo.o utilities/yes.o utilities/minibox.o utilities/ascii.o utilities/wc.o utilities/init.o utilities/ls.o utilities/touch.o utilities/ed.o utilities/sh/sh.o utilities/sh/lexer.o utilities/sh/ast.o utilities/kill.o
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) $(LIBS) -c $< -o $@
diff --git a/userland/minibox/minibox.c b/userland/minibox/minibox.c
index f3950df..e5a7f79 100644
--- a/userland/minibox/minibox.c
+++ b/userland/minibox/minibox.c
@@ -22,7 +22,7 @@ typedef struct Command {
Command utilities[] = {COMMAND(minibox), COMMAND(ascii), COMMAND(echo),
COMMAND(cat), COMMAND(yes), COMMAND(wc),
COMMAND(init), COMMAND(ls), COMMAND(touch),
- COMMAND(ed), COMMAND(sh)};
+ COMMAND(ed), COMMAND(sh), COMMAND(kill)};
char *parse_filename(char *str) {
char *tmp = NULL, *is = str;
diff --git a/userland/minibox/utilities/include.h b/userland/minibox/utilities/include.h
index b01d976..a3bd561 100644
--- a/userland/minibox/utilities/include.h
+++ b/userland/minibox/utilities/include.h
@@ -38,5 +38,6 @@ int ls_main(int argc, char **argv);
int touch_main(int argc, char **argv);
int ed_main(int argc, char **argv);
int sh_main(int argc, char **argv);
+int kill_main(int argc, char **argv);
int init_main(void);
diff --git a/userland/sh/sh.c b/userland/sh/sh.c
index 5fe7f63..e7741aa 100644
--- a/userland/sh/sh.c
+++ b/userland/sh/sh.c
@@ -2,6 +2,7 @@
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
+#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -11,6 +12,47 @@
#define IS_SPECIAL(_c) (';' == _c || '\n' == _c || '&' == _c || '|' == _c)
+struct child_process {
+ int pid;
+ struct child_process *next;
+};
+
+struct child_process *children = NULL;
+
+void add_child_process(int pid) {
+ struct child_process *new = malloc(sizeof(struct child_process));
+ new->next = NULL;
+ new->pid = pid;
+ struct child_process **entry = &children;
+ for (; *entry; entry = &(*entry)->next)
+ ;
+ *entry = new;
+}
+
+void remove_child_process(int pid) {
+ struct child_process *prev = NULL;
+ struct child_process *child = children;
+ for (; child; child = child->next) {
+ if (pid == child->pid) {
+ if (prev) {
+ prev->next = child->next;
+ } else {
+ children = child->next;
+ }
+ free(child);
+ return;
+ }
+ prev = child;
+ }
+}
+
+void slaugther_children(void) {
+ struct child_process *child = children;
+ for (; child; child = child->next) {
+ kill(child->pid, SIGTERM);
+ }
+}
+
char *PATH = "/:/bin";
int can_open(char *f) {
@@ -112,6 +154,7 @@ int execute_program(char *s, size_t l, int ignore_rc, int f_stdout,
exit(1);
}
}
+ add_child_process(pid);
close(fd[1]);
if (new_out)
@@ -213,7 +256,18 @@ char *get_line(void) {
return str;
}
+void term_handler() {
+ slaugther_children();
+ exit(0);
+}
+
int main(void) {
+ struct sigaction act = {0};
+ act.sa_handler = term_handler;
+ if (-1 == sigaction(SIGTERM, &act, NULL)) {
+ perror("sigaction");
+ return 1;
+ }
for (;;) {
printf("/ : ");
char *l = get_line();
diff --git a/userland/terminal/term.c b/userland/terminal/term.c
index 4824a59..cd75a90 100644
--- a/userland/terminal/term.c
+++ b/userland/terminal/term.c
@@ -4,6 +4,7 @@
#include <libgui.h>
#include <poll.h>
#include <pty.h>
+#include <signal.h>
#include <socket.h>
#include <stddef.h>
#include <stdint.h>
@@ -19,6 +20,8 @@ uint32_t screen_pos_x = 0;
uint32_t screen_pos_y = 0;
int serial_fd;
+int shell_pid;
+
int raw_mode = 0;
void execsh(void) {
@@ -98,8 +101,8 @@ void newtty(void) {
int m;
int s;
openpty(&m, &s, NULL, NULL, NULL);
- int pid = fork();
- if (0 == pid) {
+ shell_pid = fork();
+ if (0 == shell_pid) {
close(global_w->ws_socket);
close(global_w->bitmap_fd);
dup2(s, 0);
@@ -246,13 +249,14 @@ void run() {
}
if (WINDOWSERVER_EVENT_WINDOW_EXIT == e.type) {
close(global_w->ws_socket);
+ kill(shell_pid, SIGTERM);
exit(0);
return;
}
-// if (WINDOWSERVER_EVENT_WINDOW_RESIZE == e.type) {
-// GUI_Resize(global_w, e.vector[0], e.vector[1]);
-// continue;
-// }
+ // if (WINDOWSERVER_EVENT_WINDOW_RESIZE == e.type) {
+ // GUI_Resize(global_w, e.vector[0], e.vector[1]);
+ // continue;
+ // }
if (WINDOWSERVER_EVENT_KEYPRESS != e.type) {
continue;
}