makecindy / makecindy/cindy

iOS 模拟器构建缓存的跨进程并发仲裁(dev+packaged 双开 / --passive 多开)

Open
#2,919 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2.7k
Forks
401
Avg merge
21h 48m
Merged PRs (30d)
776

Description

### 使用场景 / Use case

dev 与 packaged 共库双开、或 dev --passive 多开时,多个 Desktop 进程共享同一 userData 下的 iOS 模拟器构建缓存。

### 当前问题 / Current limitation

PR #2899 的构建缓存复用(DerivedData + SPM checkout 按 worktree+arch 共享)用进程内 `activeBuildCacheKeys` 做互斥,但该 Set 只存在于单个 `createIOSSimulatorHost` 内,跨进程不共享。两个进程同时 build 同一 worktree 会并发写同一 DerivedData(build.db SQLite)导致锁冲突/损坏;prune 也看不到另一进程的 active builds / live artifacts。

### 期望方案 / Proposed solution

**复用既有的 O_EXLOCK 咨询锁(`acquireDarwinWriterLease`)给每个缓存 key 加跨进程锁。**

`ownership-registry-file.ts` 已有一套成熟的 `acquireDarwinWriterLease`(`openSync(..., O_NONBLOCK | O_EXLOCK)`,非阻塞 try-lock;内核在进程退出/崩溃时自动释放 fd —— 无 stale-lock、无 PID 复用边角)。把这个原语复用到缓存 key:

1. **锁文件独立目录**:`userData/ios-simulator/locks/.lock`(与 `projects/`、`spm/` 分离,避免被 prune 的 rename/rm 误删)。
2. **build 前抢锁**:对 `.lock` try-acquire;失败(另一进程持有)→ 抛 `DEVICE_BUSY`。成功后持有 fd 直到 build 结束(finally `release()`)。
3. **prune 跳过有锁 key**:prune 对每个候选 cache key 的 lock 文件 try-acquire,能拿到(= 无任何进程在用)才允许回收,检查完立即 release。跨进程 active build 因此不会被删。
4. **崩溃自恢复**:O_EXLOCK 由内核随进程退出自动释放,无需显式清理。
5. **非 Darwin 自然退化**:`acquireDarwinWriterLease` 非 Darwin 返回 null(iOS simulator 本就 Darwin-only),退回现有进程内互斥,行为不变。

### 已考虑的替代方案 / Alternatives considered

- **进程内 pid / 随机 salt 分域**:会让「进程重启后缓存失效」变成确定性高频代价(每次重启重编),破坏缓存复用核心价值 —— 不可取。
- **lockfile + PID 陈旧检测**:需处理 PID 复用、崩溃残留等边角;O_EXLOCK 内核托管更稳,且仓库已有现成原语。
- **只靠既有 SQLite WAL**:只保护 build.db,不保护 DerivedData 目录树 / SPM checkout 的并发写。

Contributor guide

Open the contributing guide

Research direction

Start with ownership-registry-file.ts and the createIOSSimulatorHost entry point, then trace the shared cache and prune paths introduced by PR #2899. Exercise concurrent dev/packaged or --passive processes using the same cache key. Done means cross-process builds are serialized, DEVICE_BUSY is reported when appropriate, prune skips locked keys, and non-Darwin behavior remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
build-system, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.