]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-process: Handle system shutdown
authorMichalis Pappas <michalis@unikraft.io>
Mon, 14 Apr 2025 14:33:40 +0000 (16:33 +0200)
committerUnikraft Bot <monkey@unikraft.io>
Wed, 30 Apr 2025 10:07:29 +0000 (10:07 +0000)
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 <michalis@unikraft.io>
Approved-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Andrei Tatar <andrei@unikraft.io>
GitHub-Closes: #1633

lib/posix-process/Makefile.uk
lib/posix-process/shutdown.c [new file with mode: 0644]

index 1b46c553dda65515f9aa9cf0097069c0130a4904..bd19ae771602375731cd7bb12ec5e6224dad80b2 100644 (file)
@@ -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 (file)
index 0000000..c77fc7a
--- /dev/null
@@ -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 <errno.h>
+#include <signal.h>
+
+#if CONFIG_LIBPOSIX_PROCESS_SIGNAL
+#include "signal/signal.h"
+#endif /* CONFIG_LIBPOSIX_PROCESS_SIGNAL */
+
+#include <uk/config.h>
+#include <uk/init.h>
+#include <uk/process.h>
+
+#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);