mirror of
https://github.com/feigeCode/navop.git
synced 2026-09-22 00:01:25 +00:00
排查文档记录的结论是:RDP 关闭超时时会把整个 adapter 连同 COM 资源一起 Box::leak,SSH 文件编辑器的分离加载/保存任务持有窗口强引用,两者都会让 已关闭的会话残留内存。本次按文档建议分三档落地,并刻意保持关闭/释放语义 不变——先建立可观测性,再改所有权。 第 1 档:低频诊断,不改任何语义 - 新增 windows_rdp_host::lifecycle_stats:进程级原子计数,明确区分 created / destroyed / quarantined,覆盖 hosts_*、wrong_thread_drops、 overlays_* 与 adapters_retired / retired_destroyed / retired_leaked_at_exit, 并派生 live_hosts() / live_overlays() / quarantined_adapters()。 - close 超时、overlay abandon、wrong-thread drop 的日志补 close_mode / retry_count / elapsed_ms / last_stage / last_error 关联字段。 - C++ 侧原先 DestroyWindow(host_window) 调用后不看结果,现挪进新的 destroy_host_window() noexcept:先取 GetWindowThreadProcessId(窗口销毁 之后 Win32 已不再报线程 id),SetLastError 后调用,再回读 GetLastError() 与 IsWindow()。失败行始终打印,成功行受 NAVOP_REMOTE_DESKTOP_DIAGNOSTICS 约束。刻意不做重试:失败只可能是跨线程调用或句柄已失效,而重试存在句柄 被复用后二次释放的风险。 第 2 档:编辑器分离任务改用弱引用 - reload_tab / save_tab 的分离任务由 cx.entity().clone() 改为 downgrade()。 根因就在这里:慢的 SFTP 往返会把已关闭的窗口连同其全部 tab 一起钉住。 - save 语义保持不变:写操作照常执行完毕,只有 UI 更新退化为 no-op。 - 新增 impl Drop for RemoteFileEditorWindow。窗口被移除时仍开着的 tab 不走 close_clean_tab,视图与 tab 计数必须在这里归还,否则计数会永久漂移。 - 结果被丢弃时打 log_task_result_discarded,用于区分「任务干净排空」与 「任务仍挂在后台」。 第 3 档:Box::leak 兜底改为 owner 线程 retirement 队列 - 三处 deadline 分支(close 超时、初始化清理超时、drain 的 poll_view_owner) 不再 Box::leak,改为交给 windows_native_retirement:owner 线程按 RETIREMENT_RETRY_INTERVAL=1s 重试 force_close,沿用已有的 borrow-free 三段式(Phase B 释放借用之后才泵 COM 消息,避免重入 App 借用), RETIREMENT_MAX_AGE=60s 有界宽限到期、或 on_app_quit 时才兜底 leak 并计数。 - WindowsNativeCloseOperation::into_leaked_adapter 更名 into_adapter,语义 仍是无 COM 调用的所有权移交,只是不再隐含「泄漏」。 - 队列本身(RetirementPolicy / Retired / RetirementQueue)是纯数据且跨平台 单测覆盖,只有 GPUI/native 接线是 Windows 专属。 验证: - cargo test -p windows_rdp_host:153 lib + 39 contract passed / 0 failed - cargo test -p remote_desktop_view --features windows-native-rdp: 280 passed / 0 failed - cargo test -p remote_file_editor:62 passed / 0 failed - 同步更新三处源文本契约测试:删去 Box::leak / into_leaked_adapter 断言, 新增「三处 deadline 路径都不得再出现 Box::leak」「retirement driver 不得 在 update_global 借用内 spawn」「销毁必须观测 DestroyWindow 结果」等不变量 未验证:真实 RDP 会话卡住 COM 回调、真实 SFTP 断连等真机路径仍是 #[ignore] + NAVOP_LIVE_* 环境变量用例,需要真实服务器。另有报告的 RDP 终端卡死(#118)根因仍未定位,本次未触碰该链路。