]> 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 faaf931279f71da2f7703e77fb69da35fe4ca36c..03604c8f6fe0c51cf7afa47336962e1b28c0622d 100644 (file)
@@ -22,6 +22,7 @@
 #define EINVAL 22
 #define ENOSPC 28
 #define EPIPE 32
+#define ESRCH 3
 #define EMFILE 24
 #define ESPIPE 29
 #define ENOSYS 38
index 3f16784f0379e66869b2544caa6ff7cd28ebd729..8f09c2a56bc582b35a9bf77fc555515b71dbd57c 100644 (file)
@@ -82,6 +82,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 aadb5b27b93a7fb7ed0999d716074df888297500..da1c1955dc6cb6d5571e5bc7206b68b1426e521d 100644 (file)
@@ -36,6 +36,7 @@ enum {
     SYSCALL_FORK = 16,
     SYSCALL_GETPPID = 17,
     SYSCALL_POLL = 18,
+    SYSCALL_KILL = 19,
 };
 
 #endif
index ee71ba99e32bd8e65509997796d9081c58b6b806..a18a6e4f7aa56a58790baa03705e0ce93803b9a7 100644 (file)
@@ -80,6 +80,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;
 
@@ -354,16 +418,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.
@@ -374,11 +439,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 bf481e8ec24a58a5b837f60b8104fc9d41457ebb..0c469b9b6bc3d438da2592559534e6c4fd3e0049 100644 (file)
@@ -923,6 +923,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 783ecdf9866f826a0a90fc92438c2cde7435e9c3..648205f39f21e05682ba154512f359f88935c072 100644 (file)
@@ -28,6 +28,7 @@ enum {
     SYSCALL_FORK = 16,
     SYSCALL_GETPPID = 17,
     SYSCALL_POLL = 18,
+    SYSCALL_KILL = 19,
 };
 
 struct pollfd {
@@ -41,6 +42,10 @@ enum {
     POLLOUT = 0x0004,
 };
 
+enum {
+    SIGKILL = 9,
+};
+
 enum {
     WNOHANG = 1,
 };
@@ -72,6 +77,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(
@@ -470,12 +486,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];