Skip to content

Commit

Permalink
fixup! [LibOS] Delay IPC leader notification until it has 0 connections
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
  • Loading branch information
stefanberger committed Jan 8, 2024
1 parent e2e17d2 commit 6a91b33
Showing 1 changed file with 14 additions and 20 deletions.
34 changes: 14 additions & 20 deletions libos/src/ipc/libos_ipc_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static ipc_callback ipc_callbacks[] = {
[IPC_MSG_FILE_LOCK_CLEAR_PID] = ipc_file_lock_clear_pid_callback,
};

static PAL_HANDLE leader_notifier;
static PAL_HANDLE g_leader_notifier;

static void ipc_leader_died_callback(void) {
/* This might happen legitimately e.g. if IPC leader is also our parent and does `wait` + `exit`
Expand All @@ -74,7 +74,7 @@ static void ipc_leader_died_callback(void) {
log_debug("IPC leader disconnected");
}

static inline int is_ipc_leader(void) {
static inline bool is_ipc_leader(void) {
return g_process_ipc_ids.self_vmid == STARTING_VMID;
}

Expand Down Expand Up @@ -112,17 +112,17 @@ static int add_ipc_connection(PAL_HANDLE handle, IDTYPE id) {
return 0;
}

static void del_ipc_connection(struct libos_ipc_connection* conn,
PAL_HANDLE* notifier) {
static void del_ipc_connection(struct libos_ipc_connection* conn) {
LISTP_DEL(conn, &g_ipc_connections, list);
g_ipc_connections_cnt--;

PalObjectDestroy(conn->handle);

free(conn);

if (notifier && g_ipc_connections_cnt == 0)
PalEventSet(*notifier);
if (is_ipc_leader() && g_ipc_connections_cnt == 0) {
PalEventSet(g_leader_notifier);
}
}

/*
Expand Down Expand Up @@ -223,7 +223,7 @@ static int receive_ipc_messages(struct libos_ipc_connection* conn) {
return 0;
}

static noreturn void ipc_worker_main(PAL_HANDLE* notifier) {
static noreturn void ipc_worker_main(void) {
/* TODO: If we had a global array of connections (instead of a list) we wouldn't have to gather
* them all here in every loop iteration, but then deletion would be slower (but deletion should
* be rare). */
Expand Down Expand Up @@ -347,7 +347,7 @@ static noreturn void ipc_worker_main(PAL_HANDLE* notifier) {
if (ret == 1) {
/* Connection closed. */
disconnect_callbacks(conn);
del_ipc_connection(conn, notifier);
del_ipc_connection(conn);
continue;
}
if (ret < 0) {
Expand All @@ -361,17 +361,12 @@ static noreturn void ipc_worker_main(PAL_HANDLE* notifier) {
* more time - in case there are messages left to be read. */
if (ret_events[i] == PAL_WAIT_ERROR) {
disconnect_callbacks(conn);
del_ipc_connection(conn, notifier);
del_ipc_connection(conn);
}
}
}

out_die:
if (notifier) {
g_ipc_connections_cnt = 0;
PalEventSet(*notifier);
}

PalProcessExit(1);
}

Expand All @@ -386,8 +381,7 @@ static int ipc_worker_wrapper(void* arg) {

log_debug("IPC worker started");

PAL_HANDLE* notifier = is_ipc_leader() ? &leader_notifier : NULL;
ipc_worker_main(notifier);
ipc_worker_main();
/* Unreachable. */
}

Expand All @@ -405,9 +399,9 @@ static int create_ipc_worker(void) {

/* IPC leader gets a notifier used in terminate_ipc_leader */
if (is_ipc_leader() &&
PalEventCreate(&leader_notifier, false, false) < 0) {
(ret = PalEventCreate(&g_leader_notifier, /*init_signaled=*/false, /*auto_clear=*/false)) < 0) {
log_error("IPC leader: PalEventCreate() failed");
return -ENOMEM;
return pal_to_unix_errno(ret);;
}

g_worker_thread = get_new_internal_thread();
Expand All @@ -434,9 +428,9 @@ int init_ipc_worker(void) {

void terminate_ipc_worker(void) {
if (is_ipc_leader()) {
PalEventClear(leader_notifier);
PalEventClear(g_leader_notifier);
while (__atomic_load_n(&g_ipc_connections_cnt, __ATOMIC_ACQUIRE) > 0 &&
PalEventWait(leader_notifier, NULL) < 0);
PalEventWait(g_leader_notifier, NULL) < 0);
}
set_pollable_event(&g_worker_thread->pollable_event);

Expand Down

0 comments on commit 6a91b33

Please sign in to comment.