test(e2e): coordinate podman cleanup with creation - #2568
Conversation
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
Standalone Podman reproduction: confirmedI reproduced the underlying failure using Podman only—no OpenShell process or code was involved. Environment
Trigger
Starting concurrently with the beginning of immediate teardown did not reproduce across thousands of overlaps. The important window is when the stop timeout expires and Podman transitions into final cleanup. On batch 8, two replacement starts failed with the exact E2E signature: The missing path belonged to the new container being started, not one of the containers being removed. ConclusionThis confirms an upstream Podman/Libpod image-mount lifecycle race. Podman generated an OCI specification referencing a Podman-owned image-overlay path that had disappeared before The E2E lifecycle gate in this PR remains useful because it fixes detached cross-test teardown and prevents the suite from hitting this runtime race. However, the standalone reproduction updates two statements in the current PR description:
Production remains potentially exposed when sandbox stop/removal overlaps another sandbox image-volume start. The longer-term supervisor-delivery alternatives described in the PR would avoid that Podman path entirely. |
Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
|
Label |
|
Closing this for now while we investigate a minimal driver-side compatibility fix that works with the older Podman version shipped by Ubuntu 24.04 without introducing global lifecycle locking. Ubuntu 24.04 installs Podman 4.9.3 from its official repositories. Although Ubuntu 24.04 remains supported, Podman 4.9 has been upstream EOL for more than two years (Podman lifecycle). This leaves users of the stock Ubuntu package on a substantially older runtime. The original failure was reproduced independently of OpenShell as a Podman image-volume lifecycle race: removing one container can interfere with another container attaching the same image volume. This PR attempted to avoid that race in the E2E harness by coordinating cleanup with creation while retaining concurrent sandbox creation. Serializing every Podman sandbox create and delete in the test suite would likely make CI more reliable, but it would also remove useful concurrency coverage and would not protect production deployments. We would prefer a narrow driver-side solution—for example, detecting and safely recovering from the affected transient Podman states with bounded cleanup and retry—while preserving concurrency for unaffected operations. We also need to clarify the support contract for Ubuntu 24.04 with its stock Podman package and validate the behavior against a current upstream Podman release. We can reopen or replace this PR once we have a focused fix that addresses the runtime behavior rather than masking it only in tests. |
Summary
Prevent automatic Podman E2E sandbox cleanup from overlapping sandbox creation in another test. The Podman lane still permits concurrent creates, while teardown is exclusive against creation; other compute backends retain their existing lifecycle concurrency.
This was exposed by an intermittent Podman E2E failure and confirmed with a standalone Podman reproducer: deleting a container using an image volume can race with another container attaching the same image.
Related Issue
No issue required: this is a localized E2E harness reliability fix with the investigation and design tradeoffs documented here.
Changes
SandboxGuardDropinstead of detaching a thread that can escape into a later test or be terminated at process exitPotential issue
The Podman driver mounts the supervisor OCI image directly into every sandbox using an image volume. A standalone Podman reproducer confirmed that one container removal can race with another container attaching the same image volume. In OpenShell, that can leave the new sandbox with an incomplete supervisor mount.
The E2E harness amplified this unlikely runtime race.
SandboxGuard::drop()previously spawned deletion in a detached thread and returned immediately, so teardown from a completed test could overlap creation in another test. The detached thread could also be terminated when an integration-test process exited.The read/write lifecycle gate is therefore enabled only when
OPENSHELL_E2E_DRIVER=podman. Joined, bounded fallback cleanup remains generic test-harness hygiene. The PR does not add a production mutex.Longer-term Podman and Docker consistency
The more durable production design may be to make Podman deliver the supervisor binary in the same way as Docker: extract the binary from the supervisor image, cache it by immutable image ID, and bind-mount the cached file read-only into each sandbox instead of mounting the complete OCI image.
Podman exposes the required stopped-container archive operation through its Docker-compatible API:
https://docs.podman.io/en/v3.0/_static/api-static.html
Implementing that design would require:
PodmanClientIf host-cache binds are not portable to Podman Machine, a digest-keyed, driver-owned Podman named volume could provide a daemon-side alternative.
This larger change should be reviewed with the original Podman driver author because image-volume sideloading was an intentional part of that driver design.
Alternatives considered
Testing
mise run pre-commitpassese2e-podmanChecklist