Avatar for the lynx-family user
lynx-family
lynx-stack
BlogDocsChangelog

Performance History

Latest Results

fix: allow known pnpm peer ranges
codex/fix-pnpm-11-config
4 hours ago
fix(genui): close TOCTOU in api-extractor lock (#2780) ## Summary Fix the CI flake on `code-style-check` where `@lynx-js/genui#api-extractor` fails with `TS7016: Could not find a declaration file for module '@lynx-js/genui/<subpackage>'`. The root cause is a TOCTOU bug in `acquireLock`, not a Turbo dependency gap. ## Evidence Failing job: https://github.com/lynx-family/lynx-stack/actions/runs/26868425349/job/79238017067 Tracing the events in the log (Turbo flushes a task's stdout at completion, so timestamps cluster): ``` 06:52:48.81 @lynx-js/genui-a2ui-prompt:build:api cache miss → rslib build ✓ "ready built in 0.17 s" ✓ "declaration files bundled successfully: dist/index.d.ts in 0.55 s" ✓ dist/index.js + dist/index.d.ts both written 06:53:01.63 @lynx-js/genui:api-extractor cache bypass, force executing $ pnpm run clean && tsc --project tsconfig.build.json ✗ index.ts(70,8): TS7016: '@lynx-js/genui/a2ui-prompt' dist/index.js implicitly has 'any' type 06:53:01.67 @lynx-js/genui-a2ui-prompt:api-extractor cache bypass, force executing $ rslib build ← runs rslib AGAIN, rewriting dist/index.{js,d.ts} ``` So `build:api` finished and emitted both `.js` and `.d.ts` 13 s before the failure. `a2ui-prompt#api-extractor`'s script then re-ran `rslib build` at roughly the same wall-clock moment as `genui#api-extractor`'s `tsc`. Turbo's dependency graph allows both `<sub>#api-extractor` and `genui#api-extractor` to run in parallel (they only share `//#build`), so `packages/genui/scripts/run-api-extractor.mjs` uses a shared file lock to serialize them. ## Root cause `acquireLock` had a TOCTOU bug: ```js const file = await open(lockPath, 'wx'); // creates an EMPTY file await file.writeFile(JSON.stringify(...)); // populates it (separate syscall) ``` A second process that hits `open(wx)` during this window gets `EEXIST`, reads the lock file, finds `""`, `JSON.parse` throws, the `catch` block calls `rm(lockPath)` and `continue`s — and on the next loop iteration `open(wx)` succeeds. **Both processes now think they hold the lock.** I reproduced this in isolation against the original code with 5 concurrent acquirers and a 50 ms simulated write delay: ``` maxConcurrent=5 (BUG: lock granted to all 5 simultaneously) maxConcurrent=1 (FIXED: properly serialized) ``` With the bug, `<sub>`'s `rslib build` rewrites `<sub>/dist/index.{js,d.ts}` while `genui`'s `tsc` reads it. Rslib emits `.js` first (~0.14 s) and `.d.ts` later (~0.60 s), so `tsc` catches a window where `dist/index.js` exists but `dist/index.d.ts` does not — exactly the TS7016 the log shows. ## Fix Wait on read/parse failures instead of deleting the lock file. Only clear it when we can prove the holder's PID is dead. ```diff try { const current = JSON.parse(await readFile(lockPath, 'utf8')); if (typeof current.pid === 'number' && !isProcessAlive(current.pid)) { - await rm(lockPath, { force: true }); - continue; + staleHolder = true; } } catch { - await rm(lockPath, { force: true }); - continue; + // Empty or unparseable — the holder is mid-write between + // open(wx) and writeFile. Wait instead of deleting. } + if (staleHolder) { + await rm(lockPath, { force: true }); + continue; + } + await sleep(retryDelayMs); ``` The redundant `rslib build` inside `<sub>#api-extractor` is preserved — once the lock serializes correctly, it runs while `genui`'s tsc waits, then `genui`'s tsc reads the freshly-emitted `dist`. It's wasted work but no longer racy. ## Test plan - [x] Concurrent acquireLock repro: 5 contenders / 50 ms write delay → `maxConcurrent=1` (was 5) - [x] `pnpm turbo run api-extractor --filter='@lynx-js/genui'` succeeds locally (6/6, dist intact) - [ ] CI `code-style-check` passes
main
9 hours ago
Merge branch 'main' into enrich-unknown-property-error
enrich-unknown-property-error
9 hours ago
chore: scope Lynx library instructions
p/wangjianliang/update-lynx-api-markers
10 hours ago

Latest Branches

CodSpeed Performance Gauge
0%
fix: pnpm 11 project config#2781
5 hours ago
fcca91c
codex/fix-pnpm-11-config
CodSpeed Performance Gauge
0%
15 hours ago
333d3b9
p/deanjingshui/physical-exlusive
CodSpeed Performance Gauge
+9%
9 hours ago
2e1d5b6
enrich-unknown-property-error
© 2026 CodSpeed Technology
Home Terms Privacy Docs