History

Add polling to desktop sidecar and fix infinite loop in findDataDirOwnershipHeld

Griffin Evans committed 4 months ago

Commit c91dcdb1 parent 9d996dc2 files · +46 −11Browse files

Unified · Split

2 files
  1. apps/desktop/src/main/sidecar.ts +33 −6
  2. apps/local/src/db/data-dir-ownership.ts +13 −5
apps/desktop/src/main/sidecar.ts+33−6
@@ -37,6 +37,8 @@ const sidecarLog = log.scope("sidecar"); · 36 unmodified lines
3737 const STDERR_TAIL_LIMIT = 8 * 1024;
3838 const READY_SENTINEL = "EXECUTOR_READY";
3939 const ATTACHED_SENTINEL = "EXECUTOR_ATTACHED";
40+const ATTACH_OWNER_TIMEOUT_MS = 15_000;
41+const ATTACH_OWNER_POLL_MS = 150;
4042
4143 // Children deliberately stopped via stopSidecar (quit, restart, update) —
4244 // their exits are expected and must not be reported as crashes.
@@ -281,6 +283,7 @@ export async function startSidecar(options: StartOptions = {}): Promise<SidecarC · 238 unmodified lines
281283 let stdoutControlBuffer = "";
282284 let resolved = false;
283285 let rejected = false;
286+ let attachedOwnerResolution: Promise<boolean> | null = null;
284287
285288 const logStdoutLine = makeLineSplitter((line) => sidecarLog.info(line));
286289 const logStderrLine = makeLineSplitter((line) => sidecarLog.error(line));
@@ -294,12 +297,21 @@ export async function startSidecar(options: StartOptions = {}): Promise<SidecarC · 7 unmodified lines
294297
295298 const resolveAttachedOwner = async (): Promise<boolean> => {
296299 if (resolved || rejected) return true;
297− const attached = await attachToReachableLocalServer(dataDir);
298− if (!attached) return false;
299− resolved = true;
300− expectedExits.add(child);
301− resolveStart(attached);
302− return true;
300+ if (!attachedOwnerResolution) {
301+ attachedOwnerResolution = waitForReachableLocalServer(dataDir)
302+ .then((attached) => {
303+ if (resolved || rejected) return true;
304+ if (!attached) return false;
305+ resolved = true;
306+ expectedExits.add(child);
307+ resolveStart(attached);
308+ return true;
309+ })
310+ .finally(() => {
311+ attachedOwnerResolution = null;
312+ });
313+ }
314+ return attachedOwnerResolution;
303315 };
304316
305317 const onStdout = (chunk: Buffer) => {
@@ -418,6 +430,21 @@ const isDaemonReachable = async (origin: string): Promise<boolean> => { · 112 unmodified lines
418430 return false;
419431 };
420432
433+const waitForReachableLocalServer = async (
434+ dataDir: string,
435+ options: { readonly requireCliDaemon?: boolean } = {},
436+): Promise<SidecarConnection | null> => {
437+ const deadline = Date.now() + ATTACH_OWNER_TIMEOUT_MS;
438+ while (Date.now() <= deadline) {
439+ const attached = await attachToReachableLocalServer(dataDir, options);
440+ if (attached) return attached;
441+ const remaining = deadline - Date.now();
442+ if (remaining <= 0) return null;
443+ await delay(Math.min(ATTACH_OWNER_POLL_MS, remaining));
444+ }
445+ return null;
446+};
447+
421448 const attachToReachableLocalServer = async (
422449 dataDir: string,
423450 options: { readonly requireCliDaemon?: boolean } = {},
apps/local/src/db/data-dir-ownership.ts+13−5
@@ -65,12 +65,20 @@ const configureOwnershipLockClient = async (client: Client): Promise<void> => { · 64 unmodified lines
6565 };
6666
6767 export const findDataDirOwnershipHeld = (cause: unknown): DataDirOwnershipHeld | null => {
68− if (cause instanceof DataDirOwnershipHeld) return cause;
69− if (!isRecord(cause)) return null;
68+ const visited = new WeakSet<object>();
69+ let current = cause;
7070
71− const nestedCause = cause.cause;
72− if (nestedCause === undefined || nestedCause === cause) return null;
73− return findDataDirOwnershipHeld(nestedCause);
71+ while (true) {
72+ if (current instanceof DataDirOwnershipHeld) return current;
73+ if (!isRecord(current)) return null;
74+ if (visited.has(current)) return null;
75+
76+ visited.add(current);
77+
78+ const nestedCause = current.cause;
79+ if (nestedCause === undefined) return null;
80+ current = nestedCause;
81+ }
7482 };
7583
7684 export const acquireDataDirOwnership = async (dataDir: string): Promise<DataDirOwnership> => {