diff options
-rw-r--r-- | kernel/arch/i386/mmu.c | 4 | ||||
-rw-r--r-- | kernel/cpu/syscall.c | 8 | ||||
-rw-r--r-- | kernel/fs/vfs.c | 12 | ||||
-rw-r--r-- | kernel/fs/vfs.h | 1 | ||||
-rw-r--r-- | kernel/includes/mmu.h | 2 | ||||
-rw-r--r-- | kernel/includes/signal.h | 1 | ||||
-rw-r--r-- | kernel/network/tcp.c | 2 | ||||
-rw-r--r-- | kernel/queue.c | 7 | ||||
-rw-r--r-- | kernel/sched/scheduler.c | 72 | ||||
-rw-r--r-- | kernel/sched/scheduler.h | 4 | ||||
-rwxr-xr-x | meta/userland.sh | 1 | ||||
-rw-r--r-- | userland/libc/include/signal.h | 1 | ||||
-rw-r--r-- | userland/minibox/Makefile | 2 | ||||
-rw-r--r-- | userland/minibox/minibox.c | 2 | ||||
-rw-r--r-- | userland/minibox/utilities/include.h | 1 | ||||
-rw-r--r-- | userland/sh/sh.c | 54 | ||||
-rw-r--r-- | userland/terminal/term.c | 16 |
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; } |