···371371 // Should we exit when no clients are connected.
372372 bool exit_when_idle;
373373374374+ // Timestamp when last client disconnected (for exit_when_idle delay)
375375+ uint64_t last_client_disconnect_ns;
376376+377377+ // How long to wait after all clients disconnect before exiting (in nanoseconds)
378378+ uint64_t exit_when_idle_delay_ns;
379379+374380 enum u_logging_level log_level;
375381376382 struct ipc_thread threads[IPC_MAX_CLIENTS];
+30-3
src/xrt/ipc/server/ipc_server_per_client_thread.c
···3535 *
3636 */
37373838+static void *
3939+delayed_exit_thread(void *_server)
4040+{
4141+ struct ipc_server *s = (struct ipc_server *)_server;
4242+4343+ // Sleep for the delay duration
4444+ os_nanosleep(s->exit_when_idle_delay_ns);
4545+4646+ // Check if we still have no clients after the delay
4747+ os_mutex_lock(&s->global_state.lock);
4848+ bool should_exit =
4949+ (s->exit_when_idle && s->global_state.connected_client_count == 0 && s->last_client_disconnect_ns > 0);
5050+ os_mutex_unlock(&s->global_state.lock);
5151+5252+ if (should_exit) {
5353+ IPC_INFO(s, "All clients disconnected for %u milliseconds, shutting down.",
5454+ (unsigned int)(s->exit_when_idle_delay_ns / U_TIME_1MS_IN_NS));
5555+ s->running = false;
5656+ }
5757+5858+ return NULL;
5959+}
6060+3861static void
3962common_shutdown(volatile struct ipc_client_state *ics)
4063{
···119142 if (ics->server->exit_on_disconnect) {
120143 ics->server->running = false;
121144 }
122122-123123- // Should we stop the server when all clients disconnect?
145145+ // Should we stop when all clients disconnect?
124146 if (ics->server->exit_when_idle && ics->server->global_state.connected_client_count == 0) {
125125- ics->server->running = false;
147147+ ics->server->last_client_disconnect_ns = os_monotonic_get_ns();
148148+149149+ struct os_thread thread;
150150+ os_thread_start(&thread, delayed_exit_thread, (void *)ics->server);
151151+ // We intentionally don't join this thread - it's fire and forget
126152 }
153153+127154128155 ipc_server_deactivate_session(ics);
129156}
+10-1
src/xrt/ipc/server/ipc_server_process.c
···5656 */
57575858DEBUG_GET_ONCE_BOOL_OPTION(exit_on_disconnect, "IPC_EXIT_ON_DISCONNECT", false)
5959-DEBUG_GET_ONCE_BOOL_OPTION(exit_when_idle, "IPC_EXIT_ON_IDLE", false)
5959+DEBUG_GET_ONCE_BOOL_OPTION(exit_when_idle, "IPC_EXIT_WHEN_IDLE", false)
6060+DEBUG_GET_ONCE_NUM_OPTION(exit_when_idle_delay_ms, "IPC_EXIT_WHEN_IDLE_DELAY_MS", 5000)
6061DEBUG_GET_ONCE_LOG_OPTION(ipc_log, "IPC_LOG", U_LOGGING_INFO)
61626263···493494 s->running = true;
494495 s->exit_on_disconnect = debug_get_bool_option_exit_on_disconnect();
495496 s->exit_when_idle = debug_get_bool_option_exit_when_idle();
497497+ s->last_client_disconnect_ns = 0;
498498+ uint64_t delay_ms = debug_get_num_option_exit_when_idle_delay_ms();
499499+ s->exit_when_idle_delay_ns = delay_ms * U_TIME_1MS_IN_NS;
496500497501 xret = xrt_instance_create(NULL, &s->xinst);
498502 if (xret != XRT_SUCCESS) {
···543547 u_var_add_log_level(s, &s->log_level, "Log level");
544548 u_var_add_bool(s, &s->exit_on_disconnect, "exit_on_disconnect");
545549 u_var_add_bool(s, &s->exit_when_idle, "exit_when_idle");
550550+ u_var_add_u64(s, &s->exit_when_idle_delay_ns, "exit_when_idle_delay_ns");
546551 u_var_add_bool(s, (bool *)&s->running, "running");
547552548553 return 0;
···919924920925 // Increment the connected client counter
921926 vs->global_state.connected_client_count++;
927927+928928+ // A client connected, so we're no longer in a delayed exit state
929929+ // (The delay thread will still check the client count before exiting)
930930+ vs->last_client_disconnect_ns = 0;
922931923932 // find the next free thread in our array (server_thread_index is -1)
924933 // and have it handle this connection