From: Tulio A M Mendes Date: Sun, 8 Feb 2026 03:53:48 +0000 (-0300) Subject: posix: add kill(SIGKILL) syscall X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=f5a2441a0e608d88334c6879f5eb4d0e4e8f4543;p=AdrOS.git posix: add kill(SIGKILL) syscall Introduce a minimal kill(pid,sig) syscall with SIGKILL support. Implement process_kill() to mark target as zombie, close its FDs with refcounting, and wake a waiting parent. Add ESRCH and a userland init.elf smoke test. --- diff --git a/include/errno.h b/include/errno.h index 1e0f2d9..1b0f418 100644 --- a/include/errno.h +++ b/include/errno.h @@ -13,6 +13,7 @@ #define EINVAL 22 #define ENOSPC 28 #define EPIPE 32 +#define ESRCH 3 #define EMFILE 24 #define ESPIPE 29 #define ENOSYS 38 diff --git a/include/process.h b/include/process.h index 09d65e0..1bb1e67 100644 --- a/include/process.h +++ b/include/process.h @@ -73,6 +73,9 @@ int process_waitpid(int pid, int* status_out, uint32_t options); // Mark current process as exiting and notify/wake a waiter (if any). void process_exit_notify(int status); +// Kill a process (minimal signals). Returns 0 on success or -errno. +int process_kill(uint32_t pid, int sig); + // Create a child process that will resume in usermode from a saved register frame. struct process* process_fork_create(uintptr_t child_as, const struct registers* child_regs); diff --git a/include/syscall.h b/include/syscall.h index 6c22752..53bce52 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -27,6 +27,7 @@ enum { SYSCALL_FORK = 16, SYSCALL_GETPPID = 17, SYSCALL_POLL = 18, + SYSCALL_KILL = 19, }; #endif diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 40ac6b4..6b576e1 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -71,6 +71,70 @@ static void process_reap_locked(struct process* p) { kfree(p); } +static void process_close_all_files_locked(struct process* p) { + if (!p) return; + for (int fd = 0; fd < PROCESS_MAX_FILES; fd++) { + struct file* f = p->files[fd]; + if (!f) continue; + p->files[fd] = NULL; + + if (f->refcount > 0) { + f->refcount--; + } + if (f->refcount == 0) { + if (f->node) { + vfs_close(f->node); + } + kfree(f); + } + } +} + +int process_kill(uint32_t pid, int sig) { + // Minimal: support SIGKILL only. + const int SIG_KILL = 9; + if (pid == 0) return -EINVAL; + if (sig != SIG_KILL) return -EINVAL; + + // Killing self: just exit via existing path. + if (current_process && current_process->pid == pid) { + process_exit_notify(128 + sig); + hal_cpu_enable_interrupts(); + schedule(); + for (;;) hal_cpu_idle(); + } + + uintptr_t flags = spin_lock_irqsave(&sched_lock); + struct process* p = process_find_locked(pid); + if (!p || p->pid == 0) { + spin_unlock_irqrestore(&sched_lock, flags); + return -ESRCH; + } + + if (p->state == PROCESS_ZOMBIE) { + spin_unlock_irqrestore(&sched_lock, flags); + return 0; + } + + process_close_all_files_locked(p); + p->exit_status = 128 + sig; + p->state = PROCESS_ZOMBIE; + + if (p->pid != 0) { + struct process* parent = process_find_locked(p->parent_pid); + if (parent && parent->state == PROCESS_BLOCKED && parent->waiting) { + if (parent->wait_pid == -1 || parent->wait_pid == (int)p->pid) { + parent->wait_result_pid = (int)p->pid; + parent->wait_result_status = p->exit_status; + parent->state = PROCESS_READY; + } + } + } + + spin_unlock_irqrestore(&sched_lock, flags); + return 0; +} + int process_waitpid(int pid, int* status_out, uint32_t options) { if (!current_process) return -ECHILD; @@ -345,16 +409,17 @@ struct process* process_create_kernel(void (*entry_point)(void)) { // Find next READY process struct process* get_next_ready_process(void) { + if (!current_process) return NULL; + if (!current_process->next) return current_process; + struct process* iterator = current_process->next; - - // Safety Break to prevent infinite loop if list broken - int count = 0; - while (iterator != current_process && count < 100) { + + // Scan the full circular list for a READY process. + while (iterator && iterator != current_process) { if (iterator->state == PROCESS_READY) { return iterator; } iterator = iterator->next; - count++; } // If current is ready/running, return it. @@ -365,11 +430,11 @@ struct process* get_next_ready_process(void) { // Assuming PID 0 is always in the list. // Search specifically for PID 0 iterator = current_process->next; - while (iterator->pid != 0) { + while (iterator && iterator->pid != 0) { iterator = iterator->next; if (iterator == current_process) break; // Should not happen } - return iterator; // Return idle task + return iterator ? iterator : current_process; } void schedule(void) { diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index b85be67..9814a39 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -914,6 +914,13 @@ static void syscall_handler(struct registers* regs) { return; } + if (syscall_no == SYSCALL_KILL) { + uint32_t pid = regs->ebx; + int sig = (int)regs->ecx; + regs->eax = (uint32_t)process_kill(pid, sig); + return; + } + regs->eax = (uint32_t)-ENOSYS; } diff --git a/user/init.c b/user/init.c index defaead..aa7b77b 100644 --- a/user/init.c +++ b/user/init.c @@ -19,6 +19,7 @@ enum { SYSCALL_FORK = 16, SYSCALL_GETPPID = 17, SYSCALL_POLL = 18, + SYSCALL_KILL = 19, }; struct pollfd { @@ -32,6 +33,10 @@ enum { POLLOUT = 0x0004, }; +enum { + SIGKILL = 9, +}; + enum { WNOHANG = 1, }; @@ -63,6 +68,17 @@ static int sys_write(int fd, const void* buf, uint32_t len) { return ret; } +static int sys_kill(int pid, int sig) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_KILL), "b"(pid), "c"(sig) + : "memory" + ); + return ret; +} + static int sys_poll(struct pollfd* fds, uint32_t nfds, int32_t timeout) { int ret; __asm__ volatile( @@ -461,12 +477,55 @@ void _start(void) { (uint32_t)(sizeof("[init] pipe dup2 read failed\n") - 1)); sys_exit(1); } + sys_write(1, "[init] pipe OK\n", (uint32_t)(sizeof("[init] pipe OK\n") - 1)); - (void)sys_close(1); (void)sys_close(pfds[0]); (void)sys_close(pfds[1]); - sys_write(1, "[init] pipe OK\n", (uint32_t)(sizeof("[init] pipe OK\n") - 1)); + int tfd = sys_open("/dev/tty", 0); + if (tfd < 0) { + sys_write(1, "[init] /dev/tty open failed\n", + (uint32_t)(sizeof("[init] /dev/tty open failed\n") - 1)); + sys_exit(1); + } + if (sys_dup2(tfd, 1) != 1) { + sys_write(1, "[init] dup2 restore tty failed\n", + (uint32_t)(sizeof("[init] dup2 restore tty failed\n") - 1)); + sys_exit(1); + } + (void)sys_close(tfd); + + { + int pid = sys_fork(); + if (pid < 0) { + sys_write(1, "[init] kill test fork failed\n", + (uint32_t)(sizeof("[init] kill test fork failed\n") - 1)); + sys_exit(1); + } + + if (pid == 0) { + for (;;) { + __asm__ volatile("nop"); + } + } + + if (sys_kill(pid, SIGKILL) < 0) { + sys_write(1, "[init] kill(SIGKILL) failed\n", + (uint32_t)(sizeof("[init] kill(SIGKILL) failed\n") - 1)); + sys_exit(1); + } + + int st = 0; + int rp = sys_waitpid(pid, &st, 0); + if (rp != pid || st != (128 + SIGKILL)) { + sys_write(1, "[init] kill test waitpid mismatch\n", + (uint32_t)(sizeof("[init] kill test waitpid mismatch\n") - 1)); + sys_exit(1); + } + + sys_write(1, "[init] kill(SIGKILL) OK\n", + (uint32_t)(sizeof("[init] kill(SIGKILL) OK\n") - 1)); + } { int fds[2];