Skip to content

Commit 85a3544

Browse files
authored
LinuxContainer: "Harden" stop (#388)
1 parent 4d47c58 commit 85a3544

2 files changed

Lines changed: 57 additions & 27 deletions

File tree

Sources/Containerization/LinuxContainer.swift

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -522,21 +522,18 @@ extension LinuxContainer {
522522
}
523523

524524
let startedState = try state.startedState("stop")
525+
let vm = startedState.vm
525526

527+
var firstError: Error?
526528
do {
527529
try await startedState.relayManager.stopAll()
530+
} catch {
531+
self.logger?.error("failed to stop relay manager: \(error)")
532+
firstError = firstError ?? error
533+
}
528534

529-
// It's possible the state of the vm is not in a great spot
530-
// if the guest panicked or had any sort of bug/fault.
531-
// First check if the vm is even still running, as trying to
532-
// use a vsock handle like below here will cause NIO to
533-
// fatalError because we'll get an EBADF.
534-
if startedState.vm.state == .stopped {
535-
state = .stopped
536-
return
537-
}
538-
539-
try await startedState.vm.withAgent { agent in
535+
do {
536+
try await vm.withAgent { agent in
540537
// First, we need to stop any unix socket relays as this will
541538
// keep the rootfs from being able to umount (EBUSY).
542539
let sockets = self.config.sockets
@@ -571,19 +568,38 @@ extension LinuxContainer {
571568

572569
try await agent.sync()
573570
}
571+
} catch {
572+
self.logger?.error("failed during guest cleanup: \(error)")
573+
firstError = firstError ?? error
574+
}
574575

575-
for process in startedState.vendedProcesses.values {
576-
try? await process._delete()
576+
for process in startedState.vendedProcesses.values {
577+
do {
578+
try await process._delete()
579+
} catch {
580+
self.logger?.error("failed to delete process \(process.id): \(error)")
581+
firstError = firstError ?? error
577582
}
583+
}
578584

579-
// Now delete the init proc
585+
do {
580586
try await startedState.process.delete()
587+
} catch {
588+
self.logger?.error("failed to delete init process: \(error)")
589+
firstError = firstError ?? error
590+
}
581591

582-
try await startedState.vm.stop()
592+
do {
593+
try await vm.stop()
583594
state = .stopped
595+
if let firstError {
596+
throw firstError
597+
}
584598
} catch {
585-
state.setErrored(error: error)
586-
throw error
599+
self.logger?.error("failed to stop VM: \(error)")
600+
let finalError = firstError ?? error
601+
state.setErrored(error: finalError)
602+
throw finalError
587603
}
588604
}
589605
}

vminitd/Sources/vminitd/Server+GRPC.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -555,18 +555,32 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid
555555
)
556556
}
557557

558-
let ctr = try await self.state.get(container: request.containerID)
558+
do {
559+
let ctr = try await self.state.get(container: request.containerID)
559560

560-
// Are we trying to delete the container itself?
561-
if request.id == request.containerID {
562-
try await ctr.delete()
563-
try await state.remove(container: request.id)
564-
} else {
565-
// Or just a single exec.
566-
try await ctr.deleteExec(id: request.id)
567-
}
561+
// Are we trying to delete the container itself?
562+
if request.id == request.containerID {
563+
try await ctr.delete()
564+
try await state.remove(container: request.id)
565+
} else {
566+
// Or just a single exec.
567+
try await ctr.deleteExec(id: request.id)
568+
}
568569

569-
return .init()
570+
return .init()
571+
} catch {
572+
log.error(
573+
"deleteProcess",
574+
metadata: [
575+
"id": "\(request.id)",
576+
"containerID": "\(request.containerID)",
577+
"error": "\(error)",
578+
])
579+
throw GRPCStatus(
580+
code: .internalError,
581+
message: "deleteProcess: \(error)"
582+
)
583+
}
570584
}
571585

572586
func startProcess(

0 commit comments

Comments
 (0)