Unmount: force while a foreground exec orphan holds the mount leaves Retained(Detach), and later unmount/force/close cannot recover

未关闭
#538 3 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

@mengmengmengqiang 已经在做这个了。

开始于 2026年11月8日。

  • #640 来自 @mengmengmengqiang —— 未关闭
  • #653 来自 @mengmengmengqiang —— 未关闭
  • #654 来自 @mengmengmengqiang —— 未关闭

评估

难度
5/5
预计耗时
一周以上
新手友好度
14/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
rust

调研方向

No file is named; the entry points are the workspace.unmount force path and sandbox.close, which return Retained(TeardownCustody { stage: Detach }) with detach Failed(EBUSY). Start by reproducing the four steps on the stated kernel and reading the code that builds ForcedFacts and the MountWork snapshot, then compare it with the no-force control path that recovers at the #497 join grace. There is no agreed outcome yet — the issue offers two options (retry detach once the holder is gone, or refuse force while a holder exists) — so the first deliverable is a decision on which, plus the /458 docs note; only then is there a patch to write.

由索引模型根据 Issue 内容生成。

描述

bug question

A forced unmount while a foreground workspace.exec orphan still holds the mount returns Retained(TeardownCustody { stage: Detach, detached: false, ... }), and from then on normal unmounts, another force, and sandbox.close all keep failing — even after the orphan command has exited. This came out of verifying #458; the clean path (no force) recovers normally.

Sequence: client SIGKILL during foreground exec → Busy → force → Retained(Detach) → no recovery

Sequence: the client dies during a foreground exec; unmount and discard return Busy; force returns Retained(Detach); after the orphan exits, later unmounts and a second force still return Retained, and close stays MountsActive. The green control has no early force and recovers.

Environment: macOS 26.5.1, OrbStack 7.2.9, kernel 7.2.9-orbstack-00391, Docker 29.8.2; LayerFS 9a03429a (#496/#497 present), real Sandbox.

Steps

  1. sandbox.create(), workspace.mount(sandbox, "lane").
  2. Start a foreground workspace.exec(ws, "sleep 20") (the command's cwd is the mount), then SIGKILL the client process that owns the exec.
  3. workspace.unmount(ws) → Busy (phase: unmount:kernel); unmount(ws, true) (discard) → Busy.
  4. While the orphan is alive, workspace.unmount(ws, true, true) (force) →
Failed: OperationFailure {
  request: ForceUnmount { ..., relinquish_unknown: false },
  cause: Retained(TeardownCustody {
    stage: Detach, detached: false,
    work: Some(MountWork { loops_configured: 2, loops_entered: 2, loops_exited: 2, loops_joined: 2, active: 0, retained: 0, ... }),
    detail: "forced drain stopped at Detach: detach Failed(EBUSY), loops Some(SessionSnapshot { phase: Joined, ... }), work Some(MountWork { active: 0, retained: 0, requests: 5, completed: 5, terminal: true })",
    forced: Some(ForcedFacts { abort: Written, detach: Busy, commit: Absent, fenced: 0 })
  })
}
  1. Wait 30 s (the sleep 20 orphan has exited). Six normal unmounts all return the same Retained(stage: Detach, detached: false); a second force also fails; sandbox.close("1") returns MountsActive with workspaces: ["/workspaces/1"].

Control

Without the early force: unmount retries at 5/10/15 s are Busy; at ~20 s (after sleep 20 exits) the normal unmount returns Unmounted (1033 ms, the #497 grace), and sandbox.close returns Closed (375 ms).

Question

Is the post-force state intended to be unrecoverable? The orphan's cwd/descriptor was still alive when the detach failed (EBUSY), so Retained(Detach) is a reasonable custody record; but once the holder is gone, there is no SDK path to retry the detach from that record. Options:

  • make a later unmount (or a second force) re-attempt the detach once the holder is gone, or
  • refuse force while a cwd/descriptor holder exists and say the caller must kill/wait first, and document that state.

At minimum, the /458 docs answer should mention that force can leave Retained(Detach) and that the workspace then cannot be unmounted or its Sandbox closed. No code change is claimed here; this is a diagnostic report with the exact custody.

Related: #458 (foreground exec client death leaves the command running and the mount Busy), #422 (Workspace/container leak), #497 (join grace, not involved in the failed force detach).

主要语言
Rust
星标
2.1k
派生
110
平均合并
23 小时 52 分钟
30 天内合并 PR
138

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

Ephemeral-AI-Lab/layerfs 的其他 Issue

查看 Ephemeral-AI-Lab/layerfs 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。