From c9d0cbce5b8655c6ca5a44feced76623a26df435 Mon Sep 17 00:00:00 2001 From: kurihada Date: Sun, 14 Dec 2025 20:44:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(session):=20=E4=BF=AE=E5=A4=8D=20getOrCreat?= =?UTF-8?q?eProject=20=E6=AD=BB=E9=94=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 读写锁嵌套导致死锁:在持有读锁的情况下尝试获取写锁。 改为先释放读锁再获取写锁,并使用双重检查模式防止竞态条件。 --- packages/core/src/session/storage.ts | 47 ++++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/core/src/session/storage.ts b/packages/core/src/session/storage.ts index 99a6a2f..4d5ada9 100644 --- a/packages/core/src/session/storage.ts +++ b/packages/core/src/session/storage.ts @@ -83,29 +83,42 @@ export class SessionStorage { const projectId = await getProjectId(workdir); const projectFile = path.join(this.projectDir, `${projectId}.json`); - using _ = await Lock.read(projectFile); + // 先尝试读取(只需读锁) + { + using _ = await Lock.read(projectFile); + try { + const content = await fs.readFile(projectFile, 'utf-8'); + return JSON.parse(content) as ProjectMetadata; + } catch { + // 项目不存在,需要创建 + } + } + // 读锁已释放,获取写锁来创建项目 + using _ = await Lock.write(projectFile); + + // 双重检查:可能其他进程已经创建了 try { const content = await fs.readFile(projectFile, 'utf-8'); return JSON.parse(content) as ProjectMetadata; } catch { - // 项目不存在,创建新项目 - const isGitRepo = await isGitRepository(workdir); - const project: ProjectMetadata = { - id: projectId, - workdir, - createdAt: new Date().toISOString(), - isGitRepo, - }; - - using __ = await Lock.write(projectFile); - await fs.writeFile(projectFile, JSON.stringify(project, null, 2), 'utf-8'); - - // 确保项目的会话目录存在 - await fs.mkdir(path.join(this.sessionDir, projectId), { recursive: true }); - - return project; + // 确实不存在,创建新项目 } + + const isGitRepo = await isGitRepository(workdir); + const project: ProjectMetadata = { + id: projectId, + workdir, + createdAt: new Date().toISOString(), + isGitRepo, + }; + + await fs.writeFile(projectFile, JSON.stringify(project, null, 2), 'utf-8'); + + // 确保项目的会话目录存在 + await fs.mkdir(path.join(this.sessionDir, projectId), { recursive: true }); + + return project; } // ========== 会话元数据管理 ==========