diff --git a/libos/include/libos_ipc.h b/libos/include/libos_ipc.h index 9fc99856cb..aeb46b60ef 100644 --- a/libos/include/libos_ipc.h +++ b/libos/include/libos_ipc.h @@ -64,7 +64,7 @@ int init_ipc_worker(void); /*! * \brief Terminate the IPC worker thread. * - * \param force Whether to force the termination even if the IPC thread is the leader + * \param force Whether to force the termination of the IPC thread */ void terminate_ipc_worker(bool force); diff --git a/libos/src/ipc/libos_ipc_worker.c b/libos/src/ipc/libos_ipc_worker.c index bc0d589afa..323e2699a9 100644 --- a/libos/src/ipc/libos_ipc_worker.c +++ b/libos/src/ipc/libos_ipc_worker.c @@ -397,10 +397,12 @@ static int create_ipc_worker(void) { } /* IPC leader gets a notifier used in terminate_ipc_leader */ - if (is_ipc_leader() && - (ret = PalEventCreate(&g_leader_notifier, /*init_signaled=*/false, /*auto_clear=*/false)) < 0) { - log_error("IPC leader: PalEventCreate() failed"); - return pal_to_unix_errno(ret);; + if (is_ipc_leader()) { + ret = PalEventCreate(&g_leader_notifier, /*init_signaled=*/false, /*auto_clear=*/false); + if (ret < 0) { + log_error("IPC leader: PalEventCreate() failed"); + return pal_to_unix_errno(ret); + } } g_worker_thread = get_new_internal_thread(); @@ -425,9 +427,10 @@ int init_ipc_worker(void) { return create_ipc_worker(); } -/* Terminate the IPC worker. If 'force' is set, the IPC leader will not wait - * until it has 0 connections but terminate immediatel, otherwise it will - * wait until all child processes have died and there are 0 connections. +/* Terminate the IPC worker. If 'force' is set, the IPC leader will not wait until it has 0 + * connections but terminate immediately, otherwise it will wait until all child processes have + * died and there are 0 connections. 'force' will for example be set when the user sends a SIGTERM + * signal to the Gramine process. */ void terminate_ipc_worker(bool force) { if (is_ipc_leader() && !force) { diff --git a/libos/src/sys/libos_exit.c b/libos/src/sys/libos_exit.c index 0b556fde0d..6beb06a859 100644 --- a/libos/src/sys/libos_exit.c +++ b/libos/src/sys/libos_exit.c @@ -18,12 +18,6 @@ #include "pal.h" static noreturn void libos_clean_and_exit(int exit_code, int term_signal) { - /* - * TODO: if we are the IPC leader, we need to either: - * 1) kill all other Gramine processes - * 2) wait for them to exit here, before we terminate the IPC helper - */ - shutdown_sync_client(); struct libos_thread* async_thread = terminate_async_worker(); @@ -53,6 +47,10 @@ static noreturn void libos_clean_and_exit(int exit_code, int term_signal) { */ release_id(get_cur_thread()->tid); + /* Terminate the IPC worker and wait until all child processes have also terminated. However, + * if we received a SIGTERM then the IPC worker will be forcefully terminated without waiting + * for child processes. Once we exit, all child proceses will the also exit. + */ terminate_ipc_worker(term_signal == SIGTERM); log_debug("process %u exited with status %d", g_process_ipc_ids.self_vmid, exit_code); @@ -147,7 +145,8 @@ noreturn void thread_exit(int error_code, int term_signal) { /* At this point other threads might be still in the middle of an exit routine, but we don't * care since the below will call `exit_group` eventually. */ - libos_clean_and_exit(term_signal ? 128 + (term_signal & ~__WCOREDUMP_BIT) : error_code, term_signal); + libos_clean_and_exit(term_signal ? 128 + (term_signal & ~__WCOREDUMP_BIT) : error_code, + term_signal); } static int mark_thread_to_die(struct libos_thread* thread, void* arg) {