Skip to content

fix(appkit): ownership-guard the typegen spawn lock with a token [F4]#426

Draft
atilafassina wants to merge 1 commit into
mainfrom
typegen-fix/lock-token
Draft

fix(appkit): ownership-guard the typegen spawn lock with a token [F4]#426
atilafassina wants to merge 1 commit into
mainfrom
typegen-fix/lock-token

Conversation

@atilafassina

Copy link
Copy Markdown
Contributor

PR4 of the typegen review-fix stack. Independent of PR1/PR2/PR3 (branches off
main). Scope: make spawn-lock release ownership-checked (F4).

The bug

The single-flight spawn lock was released by path alone — any process (a worker
whose lock had been stolen as stale, or a stray releaseSpawnLock call) could
unlink a lock it no longer owned, deleting a live worker's lock.

Changes

  • spawn-lock.tsacquireSpawnLock(lockPath, token) writes
    ${pid} ${ts} ${token}; a stale-steal recreates with the new owner's token.
    releaseSpawnLock(lockPath, token) reads the body and unlinks only when it
    carries that token (whitespace-delimited match); otherwise it's a no-op.
  • generate-types.ts — the foreground mints a random token (randomUUID),
    passes it to acquireSpawnLock and to the worker via --worker-token
    (replacing --worker-lock); the worker re-derives the lock path from its
    rootDir positional and releases with the token. Worker argv keeps
    ...process.execArgv + --wait.

Acceptance criteria (asserted)

  • A worker can release only a lock whose body carries its token; release on a
    foreign/arbitrary path is a no-op (the file survives).
  • A stale-steal writes a new token, so the displaced worker's release does not
    delete the new owner's lock.
  • Single-flight still holds for the normal (non-stale) path; the token is plumbed
    into the worker argv.

Checks

pnpm test (shared CLI), pnpm -r typecheck, pnpm check,
pnpm --filter shared build:package all green.

Note

Touches generate-types.ts, which PR3 (--no-cache) also edits. Branched
independently off main, so the two will textually conflict at merge — expected
and resolved at merge time.

This pull request and its description were written by Isaac.

The single-flight spawn lock was released by path alone: any process (a
worker whose lock had been stolen as stale, or a stray call) could unlink a
lock it no longer owned, deleting a live worker's lock.

- spawn-lock.ts: acquireSpawnLock(lockPath, token) writes `${pid} ${ts}
  ${token}`; a stale-steal recreates with the new owner's token.
  releaseSpawnLock(lockPath, token) reads the body and unlinks ONLY when it
  carries that token (whitespace-delimited match) — otherwise a no-op.
- generate-types.ts: the foreground mints a random token (randomUUID),
  passes it to acquireSpawnLock and to the worker via `--worker-token`
  (replacing `--worker-lock`); the worker re-derives the lock path from its
  rootDir positional and releases with the token. Keeps `...process.execArgv`
  + `--wait` on the worker argv.

Tests: token-match release, non-matching-token no-op, foreign/arbitrary path
no-op (file survives), steal-then-displaced-release doesn't delete the new
owner's lock; worker argv carries the token; existing single-flight cycle
preserved.

Co-authored-by: Isaac
Signed-off-by: Atila Fassina <atila@fassina.eu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant