From 9687bee166fccf120fc2dbabcbea8627218f9920 Mon Sep 17 00:00:00 2001 From: foxhui Date: Thu, 26 Mar 2026 21:08:35 +0800 Subject: [PATCH] =?UTF-8?q?revert:=20=E5=88=A0=E9=99=A4=E5=88=A9=E7=94=A8?= =?UTF-8?q?=E4=BA=92=E6=96=A5=E9=94=81=E6=9C=BA=E5=88=B6=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=82=B9=E5=87=BB=E8=B6=85=E6=97=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(ref=20#30,=20ref=20#31,=20ref=20#33)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ src/backend/pool/PoolManager.js | 2 -- src/backend/pool/Worker.js | 11 +---------- src/backend/utils/page.js | 11 ++++++++++- src/utils/asyncMutex.js | 34 --------------------------------- 5 files changed, 15 insertions(+), 47 deletions(-) delete mode 100644 src/utils/asyncMutex.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a336167..16bb702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 再次修复豆包适配器无法点击选择模型的问题 - 修复豆包超时时间跟随配置文件 +### 🔄 Changed +- **浏览器** + - 回滚互斥锁机制,不再使用互斥锁,这是一个错误的修复 + ## [3.5.9] - 2026-03-25 ### 🐛 Fixed diff --git a/src/backend/pool/PoolManager.js b/src/backend/pool/PoolManager.js index ca8e737..8f51da3 100644 --- a/src/backend/pool/PoolManager.js +++ b/src/backend/pool/PoolManager.js @@ -108,8 +108,6 @@ export class PoolManager { // 建立共享关系:设置所有者引用,并添加到所有者的共享列表 worker._browserOwner = existing.ownerWorker; existing.ownerWorker._sharedWorkers.push(worker); - // 共享同一把浏览器互斥锁 - worker._browserMutex = existing.ownerWorker._browserMutex; } else { await worker.init(); browserMap.set(worker.userDataDir, { diff --git a/src/backend/pool/Worker.js b/src/backend/pool/Worker.js index 300a39a..db7c168 100644 --- a/src/backend/pool/Worker.js +++ b/src/backend/pool/Worker.js @@ -8,7 +8,6 @@ import { logger } from '../../utils/logger.js'; import { initBrowserBase, createCursor } from '../engine/launcher.js'; import { registry } from '../registry.js'; import { tryGotoWithCheck } from '../utils/page.js'; -import { AsyncMutex } from '../../utils/asyncMutex.js'; /** * Worker 类 - 封装单个浏览器实例 @@ -41,9 +40,6 @@ export class Worker { this._isBrowserOwner = false; // 是否是浏览器的所有者(负责重启) this._browserOwner = null; // 如果是共享者,指向所有者 Worker this._sharedWorkers = []; // 如果是所有者,保存共享该浏览器的 Worker 列表 - - // 浏览器操作互斥锁(同一浏览器实例的 Worker 共享同一把锁) - this._browserMutex = new AsyncMutex(); } /** @@ -120,6 +116,7 @@ export class Worker { this.browser = sharedBrowser; this.page = await sharedBrowser.newPage(); this.page.authState = { isHandlingAuth: false }; + this.page._browserMutex = this._browserMutex; const humanizeCursorMode = this.globalConfig?.browser?.humanizeCursor; this.page._humanizeCursorMode = humanizeCursorMode; // true 表示使用项目维护的 ghost-cursor @@ -482,18 +479,12 @@ export class Worker { userDataDir: this.userDataDir }; - // 获取浏览器互斥锁(防止同一浏览器实例的多个 Worker 并发操作鼠标) - const releaseLock = await this._browserMutex.acquire(); - logger.debug('工作池', `[${this.name}] 已获取浏览器锁`, meta); - this.busyCount++; try { // 传递原始 modelId,由适配器自己解析 return await adapter.generate(subContext, prompt, paths, modelId, meta); } finally { this.busyCount--; - releaseLock(); - logger.debug('工作池', `[${this.name}] 已释放浏览器锁`, meta); } } diff --git a/src/backend/utils/page.js b/src/backend/utils/page.js index 26c58b6..638255c 100644 --- a/src/backend/utils/page.js +++ b/src/backend/utils/page.js @@ -193,7 +193,8 @@ export async function scrollToElement(page, selectorOrLocator, options = {}) { * @param {object} [options.meta={}] - 日志元数据 * @returns {Promise} 响应对象 */ -export async function waitApiResponse(page, options = {}) { +export function waitApiResponse(page, options = {}) { + const promise = (async () => { const { urlMatch, urlContains, @@ -352,5 +353,13 @@ export async function waitApiResponse(page, options = {}) { } finally { cleanup(); } + })(); + + // 关键修复:挂载一个空的 catch 处理器 + // 因为适配器通常是先调用 waitApiResponse 拿到 Promise,然后执行 safeClick,最后再 await + // 如果在 safeClick 期间页面关闭/崩溃,此 Promise 会被 reject,触发 Node.js 未捕获异常崩溃 + promise.catch(() => {}); + + return promise; } diff --git a/src/utils/asyncMutex.js b/src/utils/asyncMutex.js deleted file mode 100644 index 4baa5d9..0000000 --- a/src/utils/asyncMutex.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @fileoverview 轻量异步互斥锁 - * @description 保证同一时刻只有一个 async 任务持有锁,用于防止同一浏览器实例的多个 Worker 并发操作鼠标。 - */ - -export class AsyncMutex { - constructor() { - this._queue = []; - this._locked = false; - } - - /** - * 获取锁,返回释放函数 - * @returns {Promise<() => void>} - */ - acquire() { - return new Promise(resolve => { - const tryAcquire = () => { - if (!this._locked) { - this._locked = true; - resolve(() => { - this._locked = false; - if (this._queue.length > 0) { - this._queue.shift()(); - } - }); - } else { - this._queue.push(tryAcquire); - } - }; - tryAcquire(); - }); - } -}