Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions Sources/Containerization/LinuxPod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,14 @@ extension LinuxPod {
}

/// Stop a container from executing.
public func stopContainer(_ containerID: String) async throws {
///

@dcantah dcantah Jun 2, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I know we talked about this, but does this offer anything that just calling waitContainer right after stopContainer returns not give? If anything I'd love if we had some functionality to cache the exit code so we don't actually need to do an RPC, and then waitContainer (and wait on LinuxProcess which it just trampolines to) just returns a cached integer

/// Returns the `ExitStatus` read from the container's process when this
/// call performed the kill+reap itself. Returns `nil` for idempotent
/// stops, never-started containers, and stops issued after the VM has
/// already shut down — there is no live exit status to read in those
/// cases.
@discardableResult
public func stopContainer(_ containerID: String) async throws -> ExitStatus? {
try await self.state.withLock { state in
let createdState = try state.phase.createdState("stopContainer")

Expand All @@ -873,7 +880,7 @@ extension LinuxPod {

// Allow stop to be called multiple times
if container.state == .stopped {
return
return nil
}

// Handle containers that were hotplugged but never started
Expand All @@ -884,7 +891,7 @@ extension LinuxPod {

container.state = .stopped
state.containers[containerID] = container
return
return nil
}

guard container.state == .started, let process = container.process else {
Expand All @@ -899,11 +906,11 @@ extension LinuxPod {
if createdState.vm.state == .stopped {
container.state = .stopped
state.containers[containerID] = container
return
return nil
}

try await process.kill(.kill)
try await process.wait(timeoutInSeconds: 3)
let exitStatus = try await process.wait(timeoutInSeconds: 3)

try await createdState.vm.withAgent { agent in
// Unmount the rootfs
Expand All @@ -923,6 +930,7 @@ extension LinuxPod {
container.process = nil
container.state = .stopped
state.containers[containerID] = container
return exitStatus
} catch {
// Try to release the hotplug device and virtiofs shares even on error
try? await createdState.vm.releaseHotplug(id: containerID)
Expand Down
Loading