From 6f4d3b57f990a43b162d7bb0cc8effe08a178b4e Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sat, 13 Jan 2024 14:12:23 +0100 Subject: [PATCH 1/2] libc: fix waitpid not detecting process termination Since 452aa40770592582830c90e1dab7f58325923e31 and the change to properly return processes exit codes in the status argument, the status will never be EXIT_ZOMBIE(16) except a process was terminated by signal(16). Return from waitpid if either an error occurred (__res < 0) or we got the status of a child process (__res == cpid). Additionally fix the weird alignment of the closing braces. --- libc/src/unistd/waitpid.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libc/src/unistd/waitpid.c b/libc/src/unistd/waitpid.c index a02c2d9..b576f14 100644 --- a/libc/src/unistd/waitpid.c +++ b/libc/src/unistd/waitpid.c @@ -1,6 +1,6 @@ /// @file waitpid.c /// @brief -/// @copyright (c) 2014-2023 This file is distributed under the MIT License. +/// @copyright (c) 2014-2024 This file is distributed under the MIT License. /// See LICENSE.md for details. #include "sys/unistd.h" @@ -18,19 +18,17 @@ pid_t waitpid(pid_t pid, int *status, int options) int __status = 0; do { __inline_syscall3(__res, waitpid, pid, &__status, options); - if (__res < 0) { + if (__res != 0) { break; -} - if (__status == EXIT_ZOMBIE) { - break; -} + } if (options && WNOHANG) { break; -} + } } while (1); + if (status) { *status = __status; -} + } __syscall_return(pid_t, __res); } From ef92ba670bab7c0cf3fb0a2ee32903f95b4753c3 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sat, 13 Jan 2024 14:17:31 +0100 Subject: [PATCH 2/2] exit: properly set the process' exit code when calling exit() In order to detect the exit status using WSTATUSCODE ((status & 0xff00) >> 8) the exit code must be shifted by 8 to the left. Separate the kernel process exit logic from the actual system call. --- mentos/inc/process/scheduler.h | 4 ++++ mentos/src/process/scheduler.c | 7 ++++++- mentos/src/system/signal.c | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/mentos/inc/process/scheduler.h b/mentos/inc/process/scheduler.h index 3510d97..2817c4b 100644 --- a/mentos/inc/process/scheduler.h +++ b/mentos/inc/process/scheduler.h @@ -112,3 +112,7 @@ int sys_waitperiod(void); /// @param gid ID of the group /// @return 1 if the group is orphan, 0 otherwise. int is_orphaned_pgrp(pid_t gid); + +/// @brief Exit the current process with status +/// @param status The exit status of the current process +void do_exit(int status); diff --git a/mentos/src/process/scheduler.c b/mentos/src/process/scheduler.c index 60a32d7..1f04d6a 100644 --- a/mentos/src/process/scheduler.c +++ b/mentos/src/process/scheduler.c @@ -517,7 +517,7 @@ pid_t sys_waitpid(pid_t pid, int *status, int options) return 0; } -void sys_exit(int exit_code) +void do_exit(int exit_code) { // Get the current task. if (runqueue.curr == NULL) { @@ -573,6 +573,11 @@ void sys_exit(int exit_code) pr_debug("Process %d exited with value %d\n", runqueue.curr->pid, exit_code); } +void sys_exit(int exit_code) +{ + do_exit(exit_code << 8); +} + int sys_sched_setparam(pid_t pid, const sched_param_t *param) { list_head *it; diff --git a/mentos/src/system/signal.c b/mentos/src/system/signal.c index ec9305e..e6424a5 100644 --- a/mentos/src/system/signal.c +++ b/mentos/src/system/signal.c @@ -495,38 +495,38 @@ int do_signal(struct pt_regs *f) continue; case SIGQUIT: - sys_exit(GET_EXIT_STATUS(1)); + do_exit(GET_EXIT_STATUS(1)); continue; case SIGILL: - sys_exit(GET_EXIT_STATUS(132)); + do_exit(GET_EXIT_STATUS(132)); continue; case SIGTRAP: - sys_exit(GET_EXIT_STATUS(133)); + do_exit(GET_EXIT_STATUS(133)); continue; case SIGABRT: - sys_exit(GET_EXIT_STATUS(134)); + do_exit(GET_EXIT_STATUS(134)); continue; case SIGFPE: - sys_exit(GET_EXIT_STATUS(136) | signr); + do_exit(GET_EXIT_STATUS(136) | signr); __unlock_task_sighand(current_process); return 1; case SIGBUS: - sys_exit(GET_EXIT_STATUS(138) | signr); + do_exit(GET_EXIT_STATUS(138) | signr); __unlock_task_sighand(current_process); return 1; case SIGSEGV: - sys_exit(GET_EXIT_STATUS(139) | signr); + do_exit(GET_EXIT_STATUS(139) | signr); __unlock_task_sighand(current_process); return 1; case SIGXCPU: - sys_exit(GET_EXIT_STATUS(158) | signr); + do_exit(GET_EXIT_STATUS(158) | signr); __unlock_task_sighand(current_process); case SIGXFSZ: - sys_exit(GET_EXIT_STATUS(159) | signr); + do_exit(GET_EXIT_STATUS(159) | signr); __unlock_task_sighand(current_process); case SIGSYS: default: - sys_exit(GET_EXIT_STATUS(exit_code) | signr); + do_exit(GET_EXIT_STATUS(exit_code) | signr); __unlock_task_sighand(current_process); return 1; }