From 6993041a964649ef12bdebc32a5ca02e0a51c330 Mon Sep 17 00:00:00 2001 From: zeyad Date: Mon, 11 May 2026 03:01:12 +0600 Subject: [PATCH] pr: Fix process slot exhaustion in process lifecycle (#16) * fix process slot reuse after exit * fix terminal tty reuse after close --- src/sys/process.c | 72 +++++++++++++++++++++++++------------ src/userland/cli/bsh.c | 20 ++--------- src/userland/gui/terminal.c | 3 +- 3 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/sys/process.c b/src/sys/process.c index 4bff1ae..01fde11 100644 --- a/src/sys/process.c +++ b/src/sys/process.c @@ -29,6 +29,34 @@ static spinlock_t runqueue_lock = SPINLOCK_INIT; static uint32_t next_cpu_assign = 1; static void process_cleanup_inner(process_t *proc); +static void process_init_signal_state(process_t *proc); + +static void process_release_slot(process_t *p) { + p->pid = 0xFFFFFFFF; + p->parent_pid = 0; + p->pgid = 0; + p->cpu_affinity = 0xFFFFFFFF; + p->exited = false; + p->exit_status = 0; + p->sleep_until = 0; + p->ui_window = NULL; + p->is_terminal_proc = false; + p->tty_id = -1; + p->kill_pending = false; + p->used_memory = 0; + p->ticks = 0; + p->next = NULL; + p->kernel_stack = 0; + p->kernel_stack_alloc = NULL; + p->user_stack_alloc = NULL; + p->pml4_phys = 0; + for (int i = 0; i < MAX_PROCESS_FDS; i++) { + p->fds[i] = NULL; + p->fd_kind[i] = PROC_FD_KIND_NONE; + p->fd_flags[i] = 0; + } + process_init_signal_state(p); +} static void process_close_fd_inner(process_t *proc, int fd) { if (!proc || fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) { @@ -558,8 +586,11 @@ uint64_t process_schedule(uint64_t current_rsp) { free_kernel_stack_later[my_cpu] = cur->kernel_stack_alloc; cur->kernel_stack_alloc = NULL; + if (cur->user_stack_alloc) kfree(cur->user_stack_alloc); + cur->user_stack_alloc = NULL; free_pml4_later[my_cpu] = cur->pml4_phys; cur->pml4_phys = 0; + if (cur->parent_pid == 0) process_release_slot(cur); if (current_process[my_cpu]->is_user && current_process[my_cpu]->kernel_stack) { tss_set_stack_cpu(my_cpu, current_process[my_cpu]->kernel_stack); @@ -677,6 +708,15 @@ static void process_cleanup_inner(process_t *proc) { for (int i = 0; i < MAX_PROCESS_FDS; i++) { process_close_fd_inner(proc, i); } + + for (int i = 0; i < MAX_PROCESSES; i++) { + if (processes[i].parent_pid == proc->pid) { + processes[i].parent_pid = 0; + if (processes[i].exited && !processes[i].kill_pending) { + process_release_slot(&processes[i]); + } + } + } extern void cmd_process_finished(void); cmd_process_finished(); @@ -769,6 +809,7 @@ void process_terminate_with_status(process_t *to_delete, int status) { to_delete->user_stack_alloc = NULL; to_delete->kernel_stack_alloc = NULL; to_delete->pml4_phys = 0; + if (to_delete->parent_pid == 0) process_release_slot(to_delete); spinlock_release_irqrestore(&runqueue_lock, rflags); } @@ -840,8 +881,11 @@ uint64_t process_terminate_current(void) { free_kernel_stack_later[my_cpu] = to_delete->kernel_stack_alloc; to_delete->kernel_stack_alloc = NULL; + if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc); + to_delete->user_stack_alloc = NULL; free_pml4_later[my_cpu] = to_delete->pml4_phys; to_delete->pml4_phys = 0; + if (to_delete->parent_pid == 0) process_release_slot(to_delete); uint64_t next_rsp = current_process[my_cpu]->rsp; spinlock_release_irqrestore(&runqueue_lock, rflags); @@ -857,33 +901,14 @@ int process_reap(uint32_t caller_pid, uint32_t pid, int *status_out) { } } if (!p) return -1; - if (!p->exited) return -2; + if (!p->exited || p->kill_pending) return -2; if (p->parent_pid != caller_pid && caller_pid != 0) return -1; if (status_out) { *status_out = p->exit_status; } - p->pid = 0xFFFFFFFF; - p->parent_pid = 0; - p->pgid = 0; - p->cpu_affinity = 0xFFFFFFFF; - p->exited = false; - p->exit_status = 0; - p->sleep_until = 0; - p->ui_window = NULL; - p->is_terminal_proc = false; - p->tty_id = -1; - p->kill_pending = false; - p->used_memory = 0; - p->ticks = 0; - p->next = NULL; - for (int i = 0; i < MAX_PROCESS_FDS; i++) { - p->fds[i] = NULL; - p->fd_kind[i] = PROC_FD_KIND_NONE; - p->fd_flags[i] = 0; - } - process_init_signal_state(p); + process_release_slot(p); return 0; } @@ -916,14 +941,15 @@ int process_waitpid(uint32_t caller_pid, int target_pid, int options, int *statu } found_waitable = 1; - if (!p->exited) { + if (!p->exited || p->kill_pending) { continue; } + uint32_t reaped_pid = p->pid; if (process_reap(caller_pid, p->pid, status_out) != 0) { return -1; } - return (int)p->pid; + return (int)reaped_pid; } if (!found_child || !found_waitable) { diff --git a/src/userland/cli/bsh.c b/src/userland/cli/bsh.c index 659e1da..d643240 100644 --- a/src/userland/cli/bsh.c +++ b/src/userland/cli/bsh.c @@ -897,24 +897,10 @@ static void show_matches(const char *prompt_tmpl, const char *line, int len, cha redraw_input(prompt_tmpl, line, len, len); } -static int pid_exists(int pid) { - char path[64]; - path[0] = 0; - strcat(path, "/proc/"); - char pid_buf[16]; - itoa(pid, pid_buf); - strcat(path, pid_buf); - strcat(path, "/status"); - int fd = sys_open(path, "r"); - if (fd < 0) return 0; - char buf[8]; - int bytes = sys_read(fd, buf, sizeof(buf)); - sys_close(fd); - return bytes > 0; -} - static void wait_for_pid(int pid) { - while (pid_exists(pid)) { + while (1) { + int rc = sys_waitpid(pid, NULL, 1); + if (rc == pid || rc < 0) break; if (g_tty_id >= 0) { int fg = sys_tty_get_fg(g_tty_id); if (fg != pid) break; diff --git a/src/userland/gui/terminal.c b/src/userland/gui/terminal.c index 5d7757c..1fe4262 100644 --- a/src/userland/gui/terminal.c +++ b/src/userland/gui/terminal.c @@ -1224,7 +1224,8 @@ int main(void) { while (ui_get_event(g_win, &ev)) { if (ev.type == GUI_EVENT_CLOSE) { for (int i = 0; i < g_tab_count; i++) { - if (g_tabs[i].bsh_pid > 0) sys_kill(g_tabs[i].bsh_pid); + sys_tty_kill_all(g_tabs[i].tty_id); + sys_tty_destroy(g_tabs[i].tty_id); } sys_exit(0); } else if (ev.type == GUI_EVENT_KEY) {