From d7396089fb10f6a74c5a3c00927cacc839bd4223 Mon Sep 17 00:00:00 2001 From: Matteo Fiorini Date: Sat, 13 Jun 2026 23:52:56 +0200 Subject: [PATCH] refactor: enhance robust IO, cache container state, and secure default configuration --- .../ContainerSystemConfig.swift | 16 ++++++++++-- .../Client/ProcessIO.swift | 14 +++++++++-- .../Server/Containers/ContainersService.swift | 25 ++++--------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/Sources/ContainerPersistence/ContainerSystemConfig.swift b/Sources/ContainerPersistence/ContainerSystemConfig.swift index f0b9f36f2..439019f8e 100644 --- a/Sources/ContainerPersistence/ContainerSystemConfig.swift +++ b/Sources/ContainerPersistence/ContainerSystemConfig.swift @@ -80,7 +80,13 @@ public final class ContainerSystemConfig: Codable, Sendable, Initable { final public class BuildConfig: Codable, Sendable { public static let defaultRosetta = true public static let defaultCPUs = 2 - public static let defaultMemory = try! MemorySize("2048MB") + public static let defaultMemory: MemorySize = { + do { + return try MemorySize("2048MB") + } catch { + preconditionFailure("Errore nell'inizializzazione statica di defaultMemory: \(error)") + } + }() public static var defaultImage: String { let tag = String(cString: get_container_builder_shim_version()) return "ghcr.io/apple/container-builder-shim/builder:\(tag)" @@ -114,7 +120,13 @@ final public class BuildConfig: Codable, Sendable { final public class ContainerConfig: Codable, Sendable { public static let defaultCPUs = 4 - public static let defaultMemory = try! MemorySize("1g") + public static let defaultMemory: MemorySize = { + do { + return try MemorySize("1g") + } catch { + preconditionFailure("Errore nell'inizializzazione statica di defaultMemory: \(error)") + } + }() public let cpus: Int public let memory: MemorySize diff --git a/Sources/Services/ContainerAPIService/Client/ProcessIO.swift b/Sources/Services/ContainerAPIService/Client/ProcessIO.swift index c8189e80a..2af8306ab 100644 --- a/Sources/Services/ContainerAPIService/Client/ProcessIO.swift +++ b/Sources/Services/ContainerAPIService/Client/ProcessIO.swift @@ -105,7 +105,12 @@ public struct ProcessIO: Sendable { cc.yield() return } - try! pout.write(contentsOf: data) + do { + try pout.write(contentsOf: data) + } catch { + rout.readabilityHandler = nil + cc.yield() + } } } @@ -126,7 +131,12 @@ public struct ProcessIO: Sendable { cc.yield() return } - try! perr.write(contentsOf: data) + do { + try perr.write(contentsOf: data) + } catch { + rerr.readabilityHandler = nil + cc.yield() + } } stdio[2] = stderr.fileHandleForWriting } diff --git a/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift b/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift index a37ad6912..c78eaeb70 100644 --- a/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift +++ b/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift @@ -1026,32 +1026,17 @@ public actor ContainersService { await self.exitMonitor.stopTracking(id: id) let path = self.containerRoot.appendingPathComponent(id) - // Try to get config for service deregistration - // Don't fail if bundle is incomplete - var config: ContainerConfiguration? - let bundle = ContainerResource.Bundle(path: path) - do { - config = try bundle.configuration - } catch { - self.log.warning( - "failed to read bundle configuration during cleanup for container", - metadata: [ - "id": "\(id)", - "error": "\(error)", - ]) - } - - // Only try to deregister service if we have a valid config - // TODO: Change this so we don't have to reread the config - // possibly store the container ID to service label mapping - if let config = config { + let containerState = self.containers[id] + if let runtimeHandler = containerState?.snapshot.configuration.runtimeHandler { let label = Self.fullLaunchdServiceLabel( - runtimeName: config.runtimeHandler, + runtimeName: runtimeHandler, instanceId: id ) try? ServiceManager.deregister(fullServiceLabel: label) } + let bundle = ContainerResource.Bundle(path: path) + // Always try to delete the bundle directory, even if it's incomplete do { try bundle.delete()