]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
posix: add kill(SIGKILL) syscall
authorTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:53:48 +0000 (00:53 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:53:48 +0000 (00:53 -0300)
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.

include/errno.h
include/process.h
include/syscall.h
src/kernel/scheduler.c
src/kernel/syscall.c
user/init.c

index 1e0f2d9a352b16e332b43206f112b7091d2efde4..1b0f418a07e86af4060f1611231b6f3bd11ff07b 100644 (file)
@@ -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
index 09d65e07a09e56d07e137c60f36c19dc7d2c84be..1bb1e6758614ba92ded21c2eb720c75019c69272 100644 (file)
@@ -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);
 
index 6c22752a0ccf31f76272f239e7003c717c80880d..53bce52fad3464884e95f7869a9ebd66ba0d51be 100644 (file)
@@ -27,6 +27,7 @@ enum {
     SYSCALL_FORK = 16,
     SYSCALL_GETPPID = 17,
     SYSCALL_POLL = 18,
+    SYSCALL_KILL = 19,
 };
 
 #endif
index 40ac6b496fbaf06c60bf2f2017522a8dad973efa..6b576e1fb7f8fd77cafa185711dc0753f2e88d12 100644 (file)
@@ -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) {
index b85be6799c8448f42ec54c2834fc52641e08b8d3..9814a39013c2c704f4061818fb724b28dd1b3383 100644 (file)
@@ -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;
 }
 
index defaead565527a4bb214836cf06e8a0695a5ed97..aa7b77badc02198a77064741479acb9103f61dfb 100644 (file)
@@ -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];