diff --git a/extensions/pi-remote-control/server.ts b/extensions/pi-remote-control/server.ts index 63888a4..1560173 100644 --- a/extensions/pi-remote-control/server.ts +++ b/extensions/pi-remote-control/server.ts @@ -226,15 +226,34 @@ export function startServer(pi: ExtensionAPI, ctx: ExtensionContext): Promise - new Promise((res) => { + new Promise((res) => { + // Forcefully kill all WebSocket clients — terminate() sends no + // close frame and doesn't wait for the remote end to acknowledge, + // so it can't hang on an unresponsive client. for (const client of clients) { try { - client.close(); + client.terminate(); } catch { /* ignore */ } } - wss.close(() => httpServer.close(() => res())); + clients.clear(); + + // Safety timeout — if wss/http shutdown callbacks never fire + // (e.g. lingering keep-alive sockets), resolve anyway so the + // session_shutdown handler doesn't block pi from exiting. + const timeout = setTimeout(() => { + httpServer.close(() => {}); + httpServer.closeAllConnections?.(); + res(); + }, 2000); + + wss.close(() => + httpServer.close(() => { + clearTimeout(timeout); + res(); + }), + ); }), clientCount: () => clients.size, onClientChange: (cb: () => void) => { clientChangeListeners.push(cb); },