Skip to content

Fix/windows multi window run output leak - #413

Merged
1lck merged 3 commits into
1lck:previewfrom
Rangsh:fix/windows-multi-window-run-output-leak
Sep 2, 2026
Merged

Fix/windows multi window run output leak#413
1lck merged 3 commits into
1lck:previewfrom
Rangsh:fix/windows-multi-window-run-output-leak

Conversation

@Rangsh

@Rangsh Rangsh commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

修复 Windows 多开项目窗口时,运行/调试控制台输出串到其他窗口的问题(Fixes #408)。

根因有两处:

  1. Rust 端使用 app.emit 向所有 WebView 广播 run-output / run-exit,每个窗口的监听器都会收到并写入本地 store。
  2. 多个窗口共用 "primary" 作为 sessionId,后端进程会话以单一 ID 管理,后启动的窗口会覆盖或干扰先启动窗口的进程。

本次改动:

  • 后端以 (window_label, session_id) 复合键隔离运行进程会话。
  • run-output / run-exit 改为 emit_to(window_label, ...),仅投递到发起运行的窗口。
  • 前端在启动、停止、写入 stdin 时自动附带当前窗口的 windowLabel(Maven 任务复用同一 API,同步受益)。

关联 Issue:#408

Changes

文件 说明
windows/tauri/src-tauri/src/run.rs 窗口级会话隔离 + emit_to 定向事件投递
windows/tauri/src/features/run/api/run-host-api.ts 调用 host API 时附带 windowLabel
windows/tauri/src/features/run/utils/run-window-context.ts 获取当前 WebView 窗口标签
windows/tauri/src/features/run/api/run-host-api.test.ts 验证 API 传参包含 windowLabel

Test plan

  • cargo test --manifest-path windows/tauri/src-tauri/Cargo.toml run_session_keys
  • cargo test --manifest-path windows/tauri/src-tauri/Cargo.toml run::tests::stdin_write
  • bun test windows/tauri/src/features/run/api/run-host-api.test.ts

Notes

  • 调试器后端(debug_start_session)尚未在 Windows 端落地;本次修复覆盖 Issue 截图中的运行输出场景。调试器实现后建议采用相同的 windowLabel + emit_to 模式。

Fixes #408

按窗口标签区分运行进程会话,并将 run-output/run-exit 事件定向投递到发起窗口,避免多开项目时输出混入其他窗口。

Fixes 1lck#408

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rangsh
Rangsh requested a review from 1lck as a code owner September 2, 2026 11:34
@Rangsh
Rangsh changed the base branch from main to preview September 2, 2026 11:37
@Rangsh

Rangsh commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@lithe review

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Lithe Review

结论: ✅ 未发现明确问题
依据: Issue #408 · e4544e1 ← 1b70ce8 · head: 1b70ce8

LGTM

验证

  • 已检查四个变更文件、相关运行进程 API 调用方、事件监听器、Tauri 命令注册及 base 版本对应实现。
  • 本次审查未运行测试。

if !chunk.is_empty() {
let _ = app.emit(
let _ = app.emit_to(
&window_label,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] windows/tauri/src-tauri/src/run.rs:1474

这里改成 emit_to(&window_label, ...) 方向是对的,但单靠它可能还关不掉 #408 的串窗输出。

触发场景:两个项目窗口都挂了 listen("run-output") / listen("run-exit")(见 use-run-process-events.tsuse-maven-process-events.ts)。Tauri 2 里这种全局 listen 默认 target 是 EventTarget::Any;后端 emit_to 时,Any 监听仍会被命中,所以 B 窗口仍可能收到 A 窗口的输出。

影响:会话复合键能避免进程互踩,但用户看到的「输出串到其他窗口」很可能还在。

建议:前端改成窗口作用域监听,和 menu 事件同一套做法,例如:

const window = getCurrentWebviewWindow();
await window.listen("run-output", ...)
await window.listen("run-exit", ...)

use-run-process-events.tsuse-maven-process-events.ts 都要改。后端 emit_to + 复合键建议保留。

}
let _ = app.emit(
let _ = app.emit_to(
&window_label,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] windows/tauri/src-tauri/src/run.rs:1538

run-exit 同样走 emit_to,会踩和上面 run-output 一样的问题:全局 listen("run-exit")Any target 下仍会收到定向事件,非发起窗口可能错误地 finishProcess

建议与 output 一并改成 getCurrentWebviewWindow().listen(...),两边保持对称。

arguments: ["run", "."],
workingDirectory: "D:\\demo",
environment: {},
windowLabel: "project-window",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] windows/tauri/src/features/run/api/run-host-api.test.ts:33

这个测试能确认 invoke 带上了 windowLabel,对 API 契约有用,但盖不住 #408 的核心回归:多窗口下事件是否只进发起窗口。

现在 CI 全绿也说明不了串窗已修好(尤其是 listener 仍是全局 listen 时)。

建议补一条更贴场景的断言,例如 mock/验证 run、maven 的 listener 使用了当前 window label(或 WebviewWindow.listen)。手测两窗 run 也仍然值得做一次。

pub struct RunProcessManager;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct RunSessionKey {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P3] windows/tauri/src-tauri/src/run.rs:43

RunSessionKey { window_label, session_id } 这个建模很干净,直接对准了多窗共用 "primary" 会互踩进程的根因,后续 debug 会话也可以按同一复合键扩展。这部分建议原样保留。

@1lck

1lck commented Sep 2, 2026

Copy link
Copy Markdown
Owner

@Rangsh 看过这个 PR 了,整体方向是对的,不过 #408 的主症状我判断还没完全关上。

阻塞合并: 有。后端 emit_to(window_label)(window_label, session_id) 会话隔离都改对了,能避免多窗共用 "primary" 时互相 stop/覆盖进程。但前端 use-run-process-events / use-maven-process-events 仍是全局 listen()(Tauri 默认 EventTarget::Any)。在这个模型下,Any 监听仍会收到 emit_to 事件,所以「A 窗运行、B 窗也刷同一份输出」很可能还在。建议两处 listener 改成 getCurrentWebviewWindow().listen(...),和现有 menu 事件同一套路;后端的 emit_to + 复合键请保留。

做得好的地方: RunSessionKey 把窗口和 session 拆开,建模干净,后续 debug 也可以直接沿用;host API 自动附带 windowLabel、Maven 复用同一路径,接入面也很克制,没有往 lithe-core 乱塞平台逻辑。

验证缺口: 现有单测主要覆盖「参数带上了 windowLabel」和 key 相等性,钉不住多窗事件隔离。补完 listener 后,最好再手测一次:开两个项目窗,只在一个窗 run,确认另一个窗的 Run 面板保持安静。Windows CI 已经绿了,平台构建侧不用担心。

改完 listener 后我可以再帮看一轮。

将 use-run-process-events 与 use-maven-process-events 从全局 listen 改为 getCurrentWebviewWindow().listen,避免 Tauri EventTarget::Any 在多窗下仍接收 emit_to 事件。

补充 listener 窗口作用域单测,验证不会注册全局 listen。

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rangsh

Rangsh commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

@1lck 请你麻烦再审核一下最新的提交

@1lck 1lck left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rangsh 第二轮看过 bf842e07 了。

上次卡合并的点已经补上:use-run-process-events / use-maven-process-events 改成 getCurrentWebviewWindow().listen,和 emit_to(window_label)、会话复合键对上了;单测也断言了不会再走全局 listen。按 Tauri 2 的事件匹配规则,#408 那条串窗输出链路现在是闭环的。

未发现需要阻塞合并的问题。

值得保留的设计:RunSessionKey、host API 自动带 windowLabel、窗口级 listen,这三层是一套完整隔离,后续 debug 事件也可以直接复用。

剩余缺口主要是人工验证:Windows 上开两个项目窗,只在一个窗 run,确认另一个 Run 面板保持安静。Windows CI 这轮还在跑,合入前等它绿一下即可。PR 描述里的 Changes / Test plan 可以顺手补上 listener 相关文件(不阻塞)。

@1lck

1lck commented Sep 2, 2026

Copy link
Copy Markdown
Owner

@Rangsh 未发现需要阻塞合并的问题。整体实现方向是合理的,建议保留现有的 RunSessionKey + emit_to + 窗口级 listen 三层隔离。目前主要剩余的是 Windows 双窗手测,以及等本轮 Windows CI 跑绿。

@1lck
1lck merged commit 64a67fe into 1lck:preview Sep 2, 2026
4 checks passed
@1lck

1lck commented Sep 2, 2026

Copy link
Copy Markdown
Owner

已合入 preview。关联 issue #408 已关闭。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 多开窗口的情况下,运行调试的输出会串

2 participants