From 2f8493c1857d0e9be76ac1c85f66fbf378fa362d Mon Sep 17 00:00:00 2001 From: Michalis Pappas Date: Mon, 14 Apr 2025 16:33:40 +0200 Subject: [PATCH] lib/posix-process: Handle system shutdown Add an initcall to handle system shutdown. This serves the purpose of cleaning up process resources, and returning the application's exit status back to Unikraft. The implementation varies depending on system configuration. When multithreading is not enabled, the handler simply returns the exit status of the application. When multithreading or multiprocess are enabled, the handler sends a SIGTERM to the appliation and blocks until the application returns. It then proceeds to forcefully terminate any remaining process. When signals are not enabled the implementation falls back into forceful termination. Signed-off-by: Michalis Pappas Approved-by: Andrei Tatar Reviewed-by: Andrei Tatar GitHub-Closes: #1633 --- lib/posix-process/Makefile.uk | 1 + lib/posix-process/shutdown.c | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 lib/posix-process/shutdown.c diff --git a/lib/posix-process/Makefile.uk b/lib/posix-process/Makefile.uk index 1b46c553d..bd19ae771 100644 --- a/lib/posix-process/Makefile.uk +++ b/lib/posix-process/Makefile.uk @@ -12,6 +12,7 @@ LIBPOSIX_PROCESS_CFLAGS-$(CONFIG_LIBPOSIX_PROCESS_DEBUG) += -DUK_DEBUG LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/deprecated.c LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/exit.c LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/process.c +LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/shutdown.c LIBPOSIX_PROCESS_SRCS-y += $(LIBPOSIX_PROCESS_BASE)/wait.c LIBPOSIX_PROCESS_SRCS-$(CONFIG_LIBPOSIX_PROCESS_EXECVE) += $(LIBPOSIX_PROCESS_BASE)/arch/$(CONFIG_UK_ARCH)/execve.c|arch diff --git a/lib/posix-process/shutdown.c b/lib/posix-process/shutdown.c new file mode 100644 index 000000000..c77fc7a2e --- /dev/null +++ b/lib/posix-process/shutdown.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2024, Unikraft GmbH and The Unikraft Authors. + * Licensed under the BSD-3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + */ + +#include +#include + +#if CONFIG_LIBPOSIX_PROCESS_SIGNAL +#include "signal/signal.h" +#endif /* CONFIG_LIBPOSIX_PROCESS_SIGNAL */ + +#include +#include +#include + +#include "process.h" + +#if CONFIG_LIBPOSIX_PROCESS_MULTITHREADING +static inline void force_kill(struct posix_process *pproc) +{ + UK_ASSERT(pproc); + + if (pproc->state != POSIX_PROCESS_RUNNING) + return; + + /* Execute the exit part to let libraries clean up, but + * don't bother with releasing; we're going down anyway. + */ + pprocess_exit(pproc, POSIX_PROCESS_KILLED, SIGKILL); +} + +/* We can enter this path if UK_PID_INIT returns, or + * while it's still running via the shutdown signal. + */ +#if CONFIG_LIBPOSIX_PROCESS_SIGNAL +/* Since signals are enabled, if the application has not returned, + * send a signal and block until it terminates. Once the application + * is terminated, kill any remaining processes. + */ +static void pprocess_system_shutdown(struct uk_term_ctx *ctx __unused) +{ + struct posix_process *pproc_init; + struct posix_process *pproc; + + pproc_init = pid2pprocess(UK_PID_INIT); + + if (pproc_init && pproc_init->state == POSIX_PROCESS_RUNNING) { + pprocess_signal_send(pproc_init, SIGTERM, NULL); + uk_semaphore_down(&pproc_init->exit_semaphore); + } + + uk_pprocess_foreach(pproc) + force_kill(pproc); +} +#else /* !CONFIG_LIBPOSIX_PROCESS_SIGNAL */ +/* With signals not enabled, if the application did not return + * by now, we have no choice but kill it. Set exit status to + * SIGKILL to signify forceful termination. Along with the + * application, force-kill any remaining process. + */ +static void pprocess_system_shutdown(struct uk_term_ctx *ctx) +{ + struct posix_process *pproc_init; + struct posix_process *pproc; + + pproc_init = pid2pprocess(UK_PID_INIT); + + /* If terminated, we come from a return, + * hence the exit_code is already set. + */ + if (pproc_init && pproc_init->state == POSIX_PROCESS_RUNNING) + ctx->exit_code = 0x80 | SIGKILL; + + uk_pprocess_foreach(pproc) + force_kill(pproc); +} +#endif /* !CONFIG_LIBPOSIX_PROCESS_SIGNAL */ +#else /* !CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */ +/* Multithreading is not enabled. Return the exit code + * saved by the exit_group() / _exit() stubs. + */ +static void pprocess_system_shutdown(struct uk_term_ctx *ctx) +{ + ctx->exit_code = pprocess_exit_status; +} +#endif /* !CONFIG_LIBPOSIX_PROCESS_MULTITHREADING */ + +/* init last, term first */ +uk_late_initcall(0, pprocess_system_shutdown); -- 2.39.5