From a933aee8d13d7b0b18434603882560610ecea06f Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 12:13:10 -0800 Subject: [PATCH 01/14] Improvements to the startProcess command --- vminitd/Sources/vminitd/Server+GRPC.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 9b9d9228..2aca74b8 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -593,6 +593,26 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid return .with { $0.pid = pid } + } catch let err as ContainerizationError { + log.error( + "startProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .notFound: + throw GRPCStatus( + code: .notFound, + message: "startProcess: \(err)" + ) + default: + throw GRPCStatus( + code: .internalError, + message: "startProcess: failed to start process: \(err)" + ) + } } catch { log.error( "startProcess", @@ -601,6 +621,9 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) + if error is GRPCStatus { + throw error + } throw GRPCStatus( code: .internalError, message: "startProcess: failed to start process: \(error)" From 07b66a44ec64b858e81394c1757eb4ff2d3daa95 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 12:22:27 -0800 Subject: [PATCH 02/14] Improvements to the waitProcess command --- vminitd/Sources/vminitd/Server+GRPC.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 2aca74b8..b9ba31f2 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -697,6 +697,26 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid $0.exitCode = exitStatus.exitStatus $0.exitedAt = Google_Protobuf_Timestamp(date: exitStatus.exitedAt) } + } catch let err as ContainerizationError { + log.error( + "waitProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .notFound: + throw GRPCStatus( + code: .notFound, + message: "waitProcess: \(err)" + ) + default: + throw GRPCStatus( + code: .internalError, + message: "waitProcess: failed to wait on process: \(err)" + ) + } } catch { log.error( "waitProcess", @@ -705,6 +725,9 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) + if error is GRPCStatus { + throw error + } throw GRPCStatus( code: .internalError, message: "waitProcess: failed to wait on process: \(error)" From 0f564e6f0bd9e0157762e1e304ddc3e21db8e1eb Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 12:28:28 -0800 Subject: [PATCH 03/14] Improvements to the killProcess command --- vminitd/Sources/vminitd/Server+GRPC.swift | 46 ++++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index b9ba31f2..d22bb53e 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -525,17 +525,45 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "signal": "\(request.signal)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } + do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } - let ctr = try await self.state.get(container: request.containerID) - try await ctr.kill(execID: request.id, request.signal) + let ctr = try await self.state.get(container: request.containerID) + try await ctr.kill(execID: request.id, request.signal) - return .init() + return .init() + } catch let err as ContainerizationError { + log.error( + "killProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .notFound: + throw GRPCStatus(code: .notFound, message: "killProcess: \(err)") + default: + throw GRPCStatus(code: .internalError, message: "killProcess: failed to kill process: \(err)") + } + } catch { + log.error( + "killProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(error)", + ]) + if error is GRPCStatus { + throw error + } + throw GRPCStatus(code: .internalError, message: "killProcess: failed to kill process: \(error)") + } } func deleteProcess( From 1396faea5575092330a9927de7dd8a5dea0a185e Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 12:37:29 -0800 Subject: [PATCH 04/14] Improve the deleteProcess command --- vminitd/Sources/vminitd/Server+GRPC.swift | 60 +++++++++++++++++------ 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index d22bb53e..4afa85f2 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -576,25 +576,53 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } + do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } - let ctr = try await self.state.get(container: request.containerID) + let ctr = try await self.state.get(container: request.containerID) - // Are we trying to delete the container itself? - if request.id == request.containerID { - try await ctr.delete() - try await state.remove(container: request.id) - } else { - // Or just a single exec. - try await ctr.deleteExec(id: request.id) - } + // Are we trying to delete the container itself? + if request.id == request.containerID { + try await ctr.delete() + try await state.remove(container: request.id) + } else { + // Or just a single exec. + try await ctr.deleteExec(id: request.id) + } - return .init() + return .init() + } catch let err as ContainerizationError { + log.error( + "deleteProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .notFound: + throw GRPCStatus(code: .notFound, message: "deleteProcess: \(err)") + default: + throw GRPCStatus(code: .internalError, message: "deleteProcess: \(err)") + } + } catch { + log.error( + "deleteProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(error)", + ]) + if error is GRPCStatus { + throw error + } + throw GRPCStatus(code: .internalError, message: "deleteProcess: \(error)") + } } func startProcess( From 04444e699953bbc1e4cf3aa93db65610ade04243 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 13:00:48 -0800 Subject: [PATCH 05/14] Improvements to the ipAddrAdd command --- vminitd/Sources/vminitd/Server+GRPC.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 4afa85f2..c15510e5 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -876,7 +876,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid metadata: [ "error": "\(error)" ]) - throw GRPCStatus(code: .internalError, message: "ip-addr-add: \(error)") + throw GRPCStatus(code: .internalError, message: "failed to set IP address on interface \(request.interface): \(error)") } return .init() From e60d9ed6d7af9472ccc947cefe4fa33cda748e5f Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 13:06:20 -0800 Subject: [PATCH 06/14] Improvements to the ipRouteAddDefault command --- vminitd/Sources/vminitd/Server+GRPC.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index c15510e5..ae45f4d6 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -934,7 +934,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid metadata: [ "error": "\(error)" ]) - throw GRPCStatus(code: .internalError, message: "ip-route-add-default: \(error)") + throw GRPCStatus(code: .internalError, message: "failed to set default gateway on interface \(request.interface): \(error)") } return .init() From 5cc372e12c347055e58c50134872489a6085657c Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Tue, 4 Nov 2025 13:06:31 -0800 Subject: [PATCH 07/14] Improvements to the configureDns command --- vminitd/Sources/vminitd/Server+GRPC.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index ae45f4d6..d36f25c5 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -975,7 +975,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid metadata: [ "error": "\(error)" ]) - throw GRPCStatus(code: .internalError, message: "configure-dns: \(error)") + throw GRPCStatus(code: .internalError, message: "failed to configure DNS at location \(request.location): \(error)") } return .init() From 801729eae705ce08cef77c74cf8b0d400e2126e7 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Mon, 1 Dec 2025 16:23:28 -0800 Subject: [PATCH 08/14] Preserve `.invalidArgument` errors --- vminitd/Sources/vminitd/Server+GRPC.swift | 42 +++++++++++++++-------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index d36f25c5..91ec1a2b 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -498,6 +498,20 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid } return .init() + } catch let err as ContainerizationError { + log.error( + "createProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .invalidArgument: + throw GRPCStatus(code: .invalidArgument, message: "createProcess: failed to create process: \(err)") + default: + throw GRPCStatus(code: .internalError, message: "createProcess: failed to create process: \(err)") + } } catch { log.error( "createProcess", @@ -525,14 +539,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "signal": "\(request.signal)", ]) - do { - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + do { let ctr = try await self.state.get(container: request.containerID) try await ctr.kill(execID: request.id, request.signal) @@ -576,14 +590,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - do { - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + do { let ctr = try await self.state.get(container: request.containerID) // Are we trying to delete the container itself? From 146e6c5a56eff609de2e2184006715f41b542dcd Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Mon, 1 Dec 2025 16:42:13 -0800 Subject: [PATCH 09/14] Improve code consistency --- vminitd/Sources/vminitd/Server+GRPC.swift | 26 ++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 91ec1a2b..6575e983 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -561,7 +561,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid ]) switch err.code { case .notFound: - throw GRPCStatus(code: .notFound, message: "killProcess: \(err)") + throw GRPCStatus(code: .notFound, message: "killProcess: failed to kill process: \(err)") default: throw GRPCStatus(code: .internalError, message: "killProcess: failed to kill process: \(err)") } @@ -620,9 +620,9 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid ]) switch err.code { case .notFound: - throw GRPCStatus(code: .notFound, message: "deleteProcess: \(err)") + throw GRPCStatus(code: .notFound, message: "deleteProcess: failed to delete process: \(err)") default: - throw GRPCStatus(code: .internalError, message: "deleteProcess: \(err)") + throw GRPCStatus(code: .internalError, message: "deleteProcess: failed to delete process: \(err)") } } catch { log.error( @@ -673,15 +673,9 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid ]) switch err.code { case .notFound: - throw GRPCStatus( - code: .notFound, - message: "startProcess: \(err)" - ) + throw GRPCStatus(code: .notFound, message: "startProcess: failed to start process: \(err)") default: - throw GRPCStatus( - code: .internalError, - message: "startProcess: failed to start process: \(err)" - ) + throw GRPCStatus(code: .internalError, message: "startProcess: failed to start process: \(err)") } } catch { log.error( @@ -777,15 +771,9 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid ]) switch err.code { case .notFound: - throw GRPCStatus( - code: .notFound, - message: "waitProcess: \(err)" - ) + throw GRPCStatus(code: .notFound, message: "waitProcess: failed to wait on process: \(err)") default: - throw GRPCStatus( - code: .internalError, - message: "waitProcess: failed to wait on process: \(err)" - ) + throw GRPCStatus(code: .internalError, message: "waitProcess: failed to wait on process: \(err)") } } catch { log.error( From 1b181b6089a815f336e8fdc70179edb179f981ec Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Mon, 1 Dec 2025 17:59:02 -0800 Subject: [PATCH 10/14] Remove unnecessary checks --- vminitd/Sources/vminitd/Server+GRPC.swift | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index aa91f6d1..a0947255 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -520,9 +520,6 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - if error is GRPCStatus { - throw error - } throw GRPCStatus(code: .internalError, message: "createProcess: \(error)") } } @@ -573,9 +570,6 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - if error is GRPCStatus { - throw error - } throw GRPCStatus(code: .internalError, message: "killProcess: failed to kill process: \(error)") } } @@ -632,9 +626,6 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - if error is GRPCStatus { - throw error - } throw GRPCStatus(code: .internalError, message: "deleteProcess: \(error)") } } @@ -685,9 +676,6 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - if error is GRPCStatus { - throw error - } throw GRPCStatus( code: .internalError, message: "startProcess: failed to start process: \(error)" @@ -783,9 +771,6 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - if error is GRPCStatus { - throw error - } throw GRPCStatus( code: .internalError, message: "waitProcess: failed to wait on process: \(error)" From 8633fe60b36255a290e1c667466064cbc6a305a9 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Mon, 1 Dec 2025 18:13:47 -0800 Subject: [PATCH 11/14] Improve code consistency --- vminitd/Sources/vminitd/Server+GRPC.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index a0947255..0903fddd 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -520,7 +520,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - throw GRPCStatus(code: .internalError, message: "createProcess: \(error)") + throw GRPCStatus(code: .internalError, message: "createProcess: failed to create process: \(error)") } } @@ -626,7 +626,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(error)", ]) - throw GRPCStatus(code: .internalError, message: "deleteProcess: \(error)") + throw GRPCStatus(code: .internalError, message: "deleteProcess: failed to delete process: \(error)") } } From 22d508be16d110ceb2152d843b453e0e49bbbe32 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Fri, 5 Dec 2025 10:41:01 -0800 Subject: [PATCH 12/14] Ensure all `.invalidArgument` errors are converted into `GRPCStatus` --- vminitd/Sources/vminitd/Server+GRPC.swift | 130 ++++++++++++++-------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 0903fddd..7e052f6c 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -432,14 +432,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "configuration": "\(request.configuration.count)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + var ociSpec = try JSONDecoder().decode( ContainerizationOCI.Spec.self, from: request.configuration @@ -536,14 +536,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "signal": "\(request.signal)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) try await ctr.kill(execID: request.id, request.signal) @@ -584,14 +584,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) // Are we trying to delete the container itself? @@ -640,14 +640,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) let pid = try await ctr.start(execID: request.id) @@ -693,20 +693,36 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) let size = Terminal.Size( width: UInt16(request.columns), height: UInt16(request.rows) ) try await ctr.resize(execID: request.id, size: size) + } catch let err as ContainerizationError { + log.error( + "resizeProcess", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .invalidArgument: + throw GRPCStatus(code: .invalidArgument, message: "resizeProcess: failed to resize process: \(err)") + case .notFound: + throw GRPCStatus(code: .notFound, message: "resizeProcess: failed to resize process: \(err)") + default: + throw GRPCStatus(code: .internalError, message: "resizeProcess: failed to resize process: \(err)") + } } catch { log.error( "resizeProcess", @@ -734,14 +750,14 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) let exitStatus = try await ctr.wait(execID: request.id) @@ -788,19 +804,35 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", ]) - if !request.hasContainerID { - throw ContainerizationError( - .invalidArgument, - message: "processes in the root of the vm not implemented" - ) - } - do { + if !request.hasContainerID { + throw ContainerizationError( + .invalidArgument, + message: "processes in the root of the vm not implemented" + ) + } + let ctr = try await self.state.get(container: request.containerID) try await ctr.closeStdin(execID: request.id) return .init() + } catch let err as ContainerizationError { + log.error( + "closeProcessStdin", + metadata: [ + "id": "\(request.id)", + "containerID": "\(request.containerID)", + "error": "\(err)", + ]) + switch err.code { + case .invalidArgument: + throw GRPCStatus(code: .invalidArgument, message: "closeProcessStdin: failed to close process stdin: \(err)") + case .notFound: + throw GRPCStatus(code: .notFound, message: "closeProcessStdin: failed to close process stdin: \(err)") + default: + throw GRPCStatus(code: .internalError, message: "closeProcessStdin: failed to close process stdin: \(err)") + } } catch { log.error( "closeProcessStdin", From f5b119b8632d374a6032efd9ed151ccbd5b8f80e Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Fri, 5 Dec 2025 11:57:52 -0800 Subject: [PATCH 13/14] Optimize the error conversion --- vminitd/Sources/vminitd/Server+GRPC.swift | 73 +++++++++-------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index 7e052f6c..ffec3f06 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -44,6 +44,26 @@ private let _kill = Glibc.kill private let _sync = Glibc.sync #endif +extension ContainerizationError { + func toGRPCStatus(operation: String) -> GRPCStatus { + let message = "\(operation): \(self)" + switch self.code { + case .invalidArgument: + return GRPCStatus(code: .invalidArgument, message: message) + case .notFound: + return GRPCStatus(code: .notFound, message: message) + case .exists: + return GRPCStatus(code: .alreadyExists, message: message) + case .cancelled: + return GRPCStatus(code: .cancelled, message: message) + case .unsupported: + return GRPCStatus(code: .unimplemented, message: message) + default: + return GRPCStatus(code: .internalError, message: message) + } + } +} + extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvider { func setTime( request: Com_Apple_Containerization_Sandbox_V3_SetTimeRequest, @@ -506,12 +526,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .invalidArgument: - throw GRPCStatus(code: .invalidArgument, message: "createProcess: failed to create process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "createProcess: failed to create process: \(err)") - } + throw err.toGRPCStatus(operation: "createProcess: failed to create process") } catch { log.error( "createProcess", @@ -556,12 +571,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .notFound: - throw GRPCStatus(code: .notFound, message: "killProcess: failed to kill process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "killProcess: failed to kill process: \(err)") - } + throw err.toGRPCStatus(operation: "killProcess: failed to kill process") } catch { log.error( "killProcess", @@ -612,12 +622,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .notFound: - throw GRPCStatus(code: .notFound, message: "deleteProcess: failed to delete process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "deleteProcess: failed to delete process: \(err)") - } + throw err.toGRPCStatus(operation: "deleteProcess: failed to delete process") } catch { log.error( "deleteProcess", @@ -662,12 +667,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .notFound: - throw GRPCStatus(code: .notFound, message: "startProcess: failed to start process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "startProcess: failed to start process: \(err)") - } + throw err.toGRPCStatus(operation: "startProcess: failed to start process") } catch { log.error( "startProcess", @@ -715,14 +715,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .invalidArgument: - throw GRPCStatus(code: .invalidArgument, message: "resizeProcess: failed to resize process: \(err)") - case .notFound: - throw GRPCStatus(code: .notFound, message: "resizeProcess: failed to resize process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "resizeProcess: failed to resize process: \(err)") - } + throw err.toGRPCStatus(operation: "resizeProcess: failed to resize process") } catch { log.error( "resizeProcess", @@ -773,12 +766,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .notFound: - throw GRPCStatus(code: .notFound, message: "waitProcess: failed to wait on process: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "waitProcess: failed to wait on process: \(err)") - } + throw err.toGRPCStatus(operation: "waitProcess: failed to wait on process") } catch { log.error( "waitProcess", @@ -825,14 +813,7 @@ extension Initd: Com_Apple_Containerization_Sandbox_V3_SandboxContextAsyncProvid "containerID": "\(request.containerID)", "error": "\(err)", ]) - switch err.code { - case .invalidArgument: - throw GRPCStatus(code: .invalidArgument, message: "closeProcessStdin: failed to close process stdin: \(err)") - case .notFound: - throw GRPCStatus(code: .notFound, message: "closeProcessStdin: failed to close process stdin: \(err)") - default: - throw GRPCStatus(code: .internalError, message: "closeProcessStdin: failed to close process stdin: \(err)") - } + throw err.toGRPCStatus(operation: "closeProcessStdin: failed to close process stdin") } catch { log.error( "closeProcessStdin", From 27679ea314dccdaab0b0eb0c7a648b5bc7bd876a Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Fri, 5 Dec 2025 12:59:31 -0800 Subject: [PATCH 14/14] Support for additional error codes --- vminitd/Sources/vminitd/Server+GRPC.swift | 41 +++++++++++++++-------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/vminitd/Sources/vminitd/Server+GRPC.swift b/vminitd/Sources/vminitd/Server+GRPC.swift index ffec3f06..7c80ad14 100644 --- a/vminitd/Sources/vminitd/Server+GRPC.swift +++ b/vminitd/Sources/vminitd/Server+GRPC.swift @@ -47,20 +47,33 @@ private let _sync = Glibc.sync extension ContainerizationError { func toGRPCStatus(operation: String) -> GRPCStatus { let message = "\(operation): \(self)" - switch self.code { - case .invalidArgument: - return GRPCStatus(code: .invalidArgument, message: message) - case .notFound: - return GRPCStatus(code: .notFound, message: message) - case .exists: - return GRPCStatus(code: .alreadyExists, message: message) - case .cancelled: - return GRPCStatus(code: .cancelled, message: message) - case .unsupported: - return GRPCStatus(code: .unimplemented, message: message) - default: - return GRPCStatus(code: .internalError, message: message) - } + let code: GRPCStatus.Code = { + switch self.code { + case .invalidArgument: + return .invalidArgument + case .notFound: + return .notFound + case .exists: + return .alreadyExists + case .cancelled: + return .cancelled + case .unsupported: + return .unimplemented + case .unknown: + return .unknown + case .internalError: + return .internalError + case .interrupted: + return .unavailable + case .invalidState: + return .failedPrecondition + case .timeout: + return .deadlineExceeded + default: + return .internalError + } + }() + return GRPCStatus(code: code, message: message, cause: self) } }