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

Abierto
#538 3 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@mengmengmengqiang ya está trabajando en esto.

Desde el 8/11/2026.

  • #640 de @mengmengmengqiang — abierto
  • #653 de @mengmengmengqiang — abierto
  • #654 de @mengmengmengqiang — abierto

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
14/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
rust

Línea de trabajo

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.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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).

Lenguaje dominante
Rust
Estrellas
2.1k
Forks
110
Merge medio
23 h 52 min
PR fusionados (30 d)
138

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Ephemeral-AI-Lab/layerfs

Todos los issues de Ephemeral-AI-Lab/layerfs

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.