[P1/高] ConfirmationHook waitForConfirmation 超时竞态条件 #18

Closed
opened 2026-07-21 21:55:47 +08:00 by thzxx · 1 comment
Owner

问题类型

缺陷 / 高 / IPC 通信

文件位置

electron/harness/hooks/confirmation-hook.ts

问题描述

waitForConfirmation 使用 Promise + setTimeout 实现超时控制。
当超时与用户确认同时发生时(race condition):

  1. 超时定时器已触发,reject
  2. 同时用户点击确认,resolve
  3. Promise 状态由先到者决定,但 pending 的回调可能仍执行
  4. 内存泄漏:未清理的定时器与监听器

project_memory.md 要求:

Tool confirmation timeout is configurable via agent.confirmationTimeoutMs (30s~600s, default 120s)

影响

  • 工具执行状态不一致
  • 内存泄漏
  • 用户确认被忽略

建议修复

async waitForConfirmation(requestId: string): Promise<boolean> {
  // 使用 AbortController 统一清理
  const controller = new AbortController();
  const timer = setTimeout(() => {
    controller.abort();
  }, this.timeoutMs);

  try {
    const result = await new Promise<boolean>((resolve, reject) => {
      const onConfirm = (id: string, approved: boolean) => {
        if (id === requestId) {
          this.off('confirmation', onConfirm);
          resolve(approved);
        }
      };
      this.on('confirmation', onConfirm);

      controller.signal.addEventListener('abort', () => {
        this.off('confirmation', onConfirm);
        resolve(false); // 超时视为拒绝
      });
    });
    return result;
  } finally {
    clearTimeout(timer);
  }
}

确保监听器与定时器都被清理。

## 问题类型 缺陷 / 高 / IPC 通信 ## 文件位置 `electron/harness/hooks/confirmation-hook.ts` ## 问题描述 waitForConfirmation 使用 Promise + setTimeout 实现超时控制。 当超时与用户确认同时发生时(race condition): 1. 超时定时器已触发,reject 2. 同时用户点击确认,resolve 3. Promise 状态由先到者决定,但 pending 的回调可能仍执行 4. 内存泄漏:未清理的定时器与监听器 project_memory.md 要求: > Tool confirmation timeout is configurable via `agent.confirmationTimeoutMs` (30s~600s, default 120s) ## 影响 - 工具执行状态不一致 - 内存泄漏 - 用户确认被忽略 ## 建议修复 ```ts async waitForConfirmation(requestId: string): Promise<boolean> { // 使用 AbortController 统一清理 const controller = new AbortController(); const timer = setTimeout(() => { controller.abort(); }, this.timeoutMs); try { const result = await new Promise<boolean>((resolve, reject) => { const onConfirm = (id: string, approved: boolean) => { if (id === requestId) { this.off('confirmation', onConfirm); resolve(approved); } }; this.on('confirmation', onConfirm); controller.signal.addEventListener('abort', () => { this.off('confirmation', onConfirm); resolve(false); // 超时视为拒绝 }); }); return result; } finally { clearTimeout(timer); } } ``` 确保监听器与定时器都被清理。
thzxx added the IPC????? labels 2026-07-21 21:55:47 +08:00
Author
Owner

修复说明

文件: electron/harness/hooks/confirmation-hook.ts

修复: 采用 settled 标志 + safeResolve 包装:超时分支与确认分支互斥,先到者赢,另一分支直接 return。解决超时回调已入队时 clearTimeout 无法取消导致的竞态条件。

验证: tsc --noEmit 类型检查通过。

## 修复说明 **文件**: `electron/harness/hooks/confirmation-hook.ts` **修复**: 采用 `settled` 标志 + `safeResolve` 包装:超时分支与确认分支互斥,先到者赢,另一分支直接 return。解决超时回调已入队时 `clearTimeout` 无法取消导致的竞态条件。 **验证**: `tsc --noEmit` 类型检查通过。
thzxx closed this issue 2026-07-22 09:42:51 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: MetonaTeam/metona-ai-desktop#18