Skip to content

[R2][回归] 定位 hosted 选择复制夹具的 OpenClipboard 5 #85

Closed

Description

@JavaZeroo

真实失败与范围

PR83 Windows CI,HEAD79352f2b36f9f2a8828368ced089f6e2a6fda078、实际合并checkout939866f1cfd7ccc96fb9fdee0c6a493b6ebd3c07,默认自研核心/system。完整CTest45/46、265.77s,唯一失败是selection_bytes中的 test_real_system_copy_shortcuts_for_styled_fixture_twice 第一轮 ui-copy-bytes-system,异常 OpenClipboard: 5。准备五步及四shell已通过;不把此失败归为#81准备超时。

失败artifact12677990045,4714691B,SHA256 7575a5d82fec271625affe62a19a5f21edf97ae2a6bcd6b005f070070bcfa28f 已下载并核对。只提取selection-bytes和测试日志,保存在local/r81-main-ci;原文件不修改。

已观察与未知

  • 两个无系统CF的原两轮通过;system-0已保存forward和reverse两条完整进度,均复制了预期含中文/组合符/显式尾空格的文本,产品状态为Selected text copied。
  • 随后原流程return2、非超时、Job active0/total11/terminated0、desktopgone。没有第三条dpi-96记录、最终selection-bytes.json或frame;system-1未运行。
  • 直接抛出的OpenClipboard可来自夹具sentinel写入或独立读回;现有记录不能区分这次发生在哪个调用、打开者/所有者是谁、是否短暂占用或访问上下文错误。不能由错误5或后续绿推断根因。
  • #13已验的占用错误反馈/显式重试合同保留。此次不同于#66双方tick门槛或#73原30秒首记录缺失;没有同因证据,不重开不同触发的已完成项。

当前交付:观测与控制验证

PR86 基于 PR83,代码固定 0774d33b82745444e5629d14c758a09e2dd562bf,公开证据 f057060c685888702b7c9b95942534361b6f0d17。实际失败入口记录 stage/读写目的/nativeerror 和打开窗口、数据所有者的安全类别;明确是错误后的非原子观察。默认关闭的自有 owner 控制分别覆盖 stage6 写和 stage7 读,保留真实 execute/CF/原9阶段与2轮。清理异常不替换主错误,固定诊断不输出异常内容。

本地 default/system 定向2/2、3.57s,完整46/46、285.53s;13内部skip分列,selection模块8pass/2真实CFskip。清理异常纯反例使用最终同一测试源码、原无保护顺序exit1,修后4组合通过;原CF原因没有因此复现。首次缺声明依赖的41/46及无效对象地址断言独立保留。合同和来源。

代码及公开证据双轴审查已完成。PR86 已以 dfff1b0d788c756f025a718568e663bffb1a16bf 合入 PR83 分支;其真实 hosted 控制和原两轮结果如下。原 OpenClipboard5 根因保持未知,本项继续开放。

有界交付与验收

  • 在实际夹具clipboard调用入口保留固定阶段、读/写目的、原生错误及可安全归类的占用/归属边界;公开摘要不含其他进程标题/文本/路径或系统剪贴板内容。
  • 在同一源码/hosted环境区分夹具与产品复制路径、占用与权限/上下文;采用有界观察或自有owner握手建立真red,不用重复CI取绿、任意sleep或放宽精确字节。
  • 基于证据作最小修复,并保留真实queued Ctrl+Shift+C、反向/受控DPI/空选区/输入隔离、所有9阶段和原两轮;产品占用反馈/用户重试策略不被夹具修正悄悄改变。
  • 验证失败时保持原错误和退出,正常流程独立读回与Job/desktop清理完整;原触发red→green、必要负例、固定声明配置完整回归通过。
  • 同步[R2][回归] 收敛 Windows 可靠性与历史未闭合失败 #38/[R2-12][交付] 构建并验收 Windows R2 基础开发包 #35、PR83与来源/能力说明。无法复现则保留原根因未知及下一可证伪假设,不当作修复。

父项#38,本项可独立开始。真实系统CF只在既有指定一次性hosted VM执行;个人Windows剪贴板保持保护,不伪造hosted环境。

同源码 hosted 控制与原流程

HEAD f057060c685888702b7c9b95942534361b6f0d17、checkout e98466a5bce9747858e2bbd18c01f4c68747f779,Windows default/system 完整46/46、270.69s;Ubuntu和External candidate40384977349独立通过。artifact12680781542、4356796B、SHA256 479067d783b1cd0a10a30775e77582545adc189e23a19472c18523967dcf01e8 已核对;本地只离线读取产物,未调用系统CF或伪造hosted环境。

  • 真实自有owner占用:stage6 sentinel-write与stage7 readback均OpenClipboard5、exit2、非超时;open_window/data_owner均same-process-window,release_event/thread_exited为true,四个error字段全部0。
  • 原system两轮与data-only两轮均完成原9阶段、精确选择/复制快照、exit0;六例Job均active0/total11/terminated0,desktopgone。
  • 这证明观测和受控错误路径,不证明原事件由同一原因触发;当时的调用、占用/访问上下文仍未知。产品占用反馈/重试政策未变。原因修复与完整R2可靠性出口仍未完成。

主线整合

PR83 已以 8a13782aaac03780617e177b56ec55d3cb9c79be 合入 main。最终 HEAD dfff1b0d788c756f025a718568e663bffb1a16bf / checkout 683711dcb7028f2c4249ad5b1f3155c66c7a39ff 的 Windows default/system 完整回归 为46/46、241.44s,准备守卫23/23、0.128s;Ubuntu及 External candidate 独立通过。该集成结果验证观测与受控失败路径,原事件原因仍未知,本项保持开放。

另一个选择复制入口的真实失败

PR101 push/default Windows run40459936505 / job122041868650,checkout b9789543a792b0a0b96139377ea43f4dfab46626,默认核心/system。shell40项为38pass、1error、1skip,82.813s;此处失败是 test_mouse_selection_to_real_system_clipboard 的 ui-copy-system 第二轮,与原ui-copy-bytes-system入口分列,尚无同因证据。完整CTest50/52的另一失败是PR101临时工作流路径计数断言,不能归因于CF。

artifact12714865514,4269771B,ZIP SHA 4b597e169d36624c87a6a9859e0fc3b2a37846569bca3eaca4c51322ec7d2791已与GitHub digest核对;两轮原件保存在私有local/r99/hosted-copy-failure。第一轮原validator离线重算通过(12基础阶段/28交互),exit0;第二轮exit2、非超时、stderr为OpenClipboard: 5,Job active0/total11/terminated0,desktop gone,没有cleanup error。

第二轮已写12条selection-base、22条interaction,最后是system-copy-popup,含实际菜单复制成功后独立读回;缺system-copy-occupied-prepared、最终selection.json及frame。固定源码在这两条记录之间依次有sentinel写、第一次读回和为下一条interaction读取CF;具体哪个OpenClipboard调用失败、占用/权限原因仍未知。自有占用owner在下一条记录之后才构造,不能把错误直接归到那个owner。保留原场景、字节及期限;不重试取绿,不将#99两轮通过视为本项修复。

Activity

  1. added
    bugSomething isn't working
    ready-for-agent范围明确且真实阻塞已解除,可开始实施
    compatibility平台、协议或行为兼容问题
    on Oct 26, 2026
  2. added 3 commits that reference this issue on Oct 26, 2026
  3. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    定位与缓解完成

    现象与错误语义

    hosted 上偶发的 Copy failed: OpenClipboard: 5 是 ERROR_ACCESS_DENIED:Windows 规定当另一个窗口已打开剪贴板时 OpenClipboard 返回该错误。夹具本身是可重复的(多数轮次通过),因此不是窗口站被永久拒绝,而是桌面剪贴板的短暂占用(Explorer/相邻进程)。

    处置

    验证(hosted,main 2aa0723)

    • push 运行 40915083459:63/63 全部通过,其中 selection_bytes(含复制失败负向用例)Passed 8.23s;
    • 专项复现作业 windows-2025-actions-repeat 在读重试后连续两轮 20/20 全绿(修复前约 2/5 轮命中 stage-35 超时)。

    结论

    该失败是托管桌面上的瞬时剪贴板占用,不是夹具或产品逻辑缺陷;有限重试后不再表现为 45 秒级超时或复制失败,且负向用例仍然按契约失败。据此关闭本项;若未来仍出现持续占用(>200 ms),会由现有 holder 诊断(GetOpenClipboardWindow)继续定位。

  4. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    复现:OpenClipboard: 5 再次出现,但这次在夹具准备阶段

    run 40967696333(5 次重复版,main 7e29a4c):

    ValueError: shell probe failed: clipboard case=oversize phase=prepare-owner before-product-paste: OpenClipboard: 5
    

    与上次关闭时的定位一致(桌面剪贴板短暂占用),但失败点不同:

    • 之前是产品读/写路径在占用时失败;
    • 本次是夹具自己在 stage 3 调用 write_unicode_clipboard / write_oversized_clipboard 准备"占用"场景时失败——即夹具要写剪贴板却被别人(Explorer 或上一用例残留)占着。

    处置(只动夹具准备,不动产品断言)

    给这两处准备写入加了有界重试(4 次,退避 50/100/150 ms,总计 ≤300 ms);失败时仍抛出原来的错误文本。

    产品侧读/写路径的重试(PR #191/#192)保持不变;负向契约(夹具故意长期持有时产品仍失败)也不变。

    边界

    • 这是测试设置的容错,不是产品行为修改;
    • 若下次仍在 prepare-owner 失败,说明占用时间超过 300 ms,需要另议(改夹具协议或延长设置预算),不会静默吞掉。

    已在 PR #212 中随 stage 5 诊断一并提交。

  5. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    新样本:剪贴板 owner 的清理失败,错误码归属可疑

    run 40975325252:test_mouse_selection_to_real_system_clipboard 失败:

    [TF-CLIPBOARD-OWNER] clipboard owner failed its bounded ready handshake:
    mode=occupied step=DestroyWindow-cleanup win32_error=5 worker_error=5
    

    判读

    • DestroyWindow 失败时不会可靠设置 GetLastError,所以这里的 win32_error=5 很可能来自**前一次调用(CloseClipboard-cleanup)**的残留错误码;
    • 也就是说,当前记录把"真正的失败点"掩盖成了 DestroyWindow。

    处置(PR #217)

    两处清理调用前显式 SetLastError(0)(CloseClipboard-cleanup、DestroyWindow-cleanup),确保失败记录里的错误码来自该步骤本身。

    不改清理顺序、不做重试、不改期限;本次只提升诊断精度,等下一次命中拿到准确步骤与错误码再定位根因。

  6. added 2 commits that reference this issue on Oct 30, 2026
  7. removed
    ready-for-agent范围明确且真实阻塞已解除,可开始实施
    on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcompatibility平台、协议或行为兼容问题

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions