mirror of
https://github.com/apple/container.git
synced 2026-09-11 18:25:41 +00:00
LinuxContainer: Remove SendableProperty usage (#223)
The state updates because of the way the macro works weren't actually being performed under the lock.
This commit is contained in:
@@ -20,7 +20,6 @@ import ContainerizationExtras
|
||||
import ContainerizationOCI
|
||||
import Foundation
|
||||
import Logging
|
||||
import SendableProperty
|
||||
import Synchronization
|
||||
|
||||
import struct ContainerizationOS.Terminal
|
||||
@@ -142,8 +141,7 @@ public final class LinuxContainer: Container, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
@SendablePropertyUnchecked
|
||||
private var state: State
|
||||
private let state: Mutex<State>
|
||||
|
||||
// Ports to be allocated from for stdio and for
|
||||
// unix socket relays that are sharing a guest
|
||||
@@ -232,7 +230,6 @@ public final class LinuxContainer: Container, Sendable {
|
||||
.invalidState,
|
||||
message: "container must be in creating state before created"
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +325,7 @@ public final class LinuxContainer: Container, Sendable {
|
||||
try configuration(&config)
|
||||
|
||||
self.config = config
|
||||
self.state = .initialized
|
||||
self.state = Mutex(.initialized)
|
||||
}
|
||||
|
||||
private static func createDefaultRuntimeSpec(_ id: String) -> Spec {
|
||||
@@ -404,7 +401,7 @@ extension LinuxContainer {
|
||||
/// Create the underlying container's virtual machine
|
||||
/// and set up the runtime environment.
|
||||
public func create() async throws {
|
||||
try state.setCreating()
|
||||
try self.state.withLock { try $0.setCreating() }
|
||||
|
||||
let vm = try vmm.create(container: self)
|
||||
try await vm.start()
|
||||
@@ -449,19 +446,18 @@ extension LinuxContainer {
|
||||
try await agent.configureHosts(config: hosts, location: rootfs.destination)
|
||||
}
|
||||
|
||||
try state.setCreated(vm: vm, relayManager: relayManager)
|
||||
try self.state.withLock { try $0.setCreated(vm: vm, relayManager: relayManager) }
|
||||
}
|
||||
} catch {
|
||||
try? await vm.stop()
|
||||
|
||||
state.errored(error: error)
|
||||
self.state.withLock { $0.errored(error: error) }
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/// Start the container container's initial process.
|
||||
public func start() async throws {
|
||||
let vm = try state.setStarting()
|
||||
let vm = try self.state.withLock { try $0.setStarting() }
|
||||
|
||||
let agent = try await vm.dialAgent()
|
||||
do {
|
||||
@@ -487,11 +483,10 @@ extension LinuxContainer {
|
||||
)
|
||||
try await process.start()
|
||||
|
||||
try state.setStarted(process: process)
|
||||
try self.state.withLock { try $0.setStarted(process: process) }
|
||||
} catch {
|
||||
try? await agent.close()
|
||||
|
||||
state.errored(error: error)
|
||||
self.state.withLock { $0.errored(error: error) }
|
||||
throw error
|
||||
}
|
||||
}
|
||||
@@ -538,7 +533,7 @@ extension LinuxContainer {
|
||||
|
||||
/// Stop the container from executing.
|
||||
public func stop() async throws {
|
||||
let startedState = try state.stopping()
|
||||
let startedState = try self.state.withLock { try $0.stopping() }
|
||||
|
||||
try await startedState.relayManager.stopAll()
|
||||
|
||||
@@ -548,7 +543,7 @@ extension LinuxContainer {
|
||||
// use a vsock handle like below here will cause NIO to
|
||||
// fatalError because we'll get an EBADF.
|
||||
if startedState.vm.state == .stopped {
|
||||
try state.stopped()
|
||||
try self.state.withLock { try $0.stopped() }
|
||||
return
|
||||
}
|
||||
|
||||
@@ -590,32 +585,32 @@ extension LinuxContainer {
|
||||
try? await startedState.process.delete()
|
||||
|
||||
try await startedState.vm.stop()
|
||||
try state.stopped()
|
||||
try self.state.withLock { try $0.stopped() }
|
||||
}
|
||||
|
||||
/// Send a signal to the container.
|
||||
public func kill(_ signal: Int32) async throws {
|
||||
let state = try self.state.startedState("kill")
|
||||
let state = try self.state.withLock { try $0.startedState("kill") }
|
||||
try await state.process.kill(signal)
|
||||
}
|
||||
|
||||
/// Wait for the container to exit. Returns the exit code.
|
||||
@discardableResult
|
||||
public func wait(timeoutInSeconds: Int64? = nil) async throws -> Int32 {
|
||||
let state = try self.state.startedState("wait")
|
||||
let state = try self.state.withLock { try $0.startedState("wait") }
|
||||
return try await state.process.wait(timeoutInSeconds: timeoutInSeconds)
|
||||
}
|
||||
|
||||
/// Resize the container's terminal (if one was requested). This
|
||||
/// will error if terminal was set to false before creating the container.
|
||||
public func resize(to: Terminal.Size) async throws {
|
||||
let state = try self.state.startedState("resize")
|
||||
let state = try self.state.withLock { try $0.startedState("resize") }
|
||||
try await state.process.resize(to: to)
|
||||
}
|
||||
|
||||
/// Execute a new process in the container.
|
||||
public func exec(_ id: String, configuration: (inout Configuration.Process) throws -> Void) async throws -> LinuxProcess {
|
||||
let state = try self.state.startedState("exec")
|
||||
let state = try self.state.withLock { try $0.startedState("exec") }
|
||||
|
||||
var spec = generateRuntimeSpec()
|
||||
var config = Configuration.Process()
|
||||
@@ -643,7 +638,7 @@ extension LinuxContainer {
|
||||
|
||||
/// Execute a new process in the container.
|
||||
public func exec(_ id: String, configuration: Configuration.Process) async throws -> LinuxProcess {
|
||||
let state = try self.state.startedState("exec")
|
||||
let state = try self.state.withLock { try $0.startedState("exec") }
|
||||
|
||||
var spec = generateRuntimeSpec()
|
||||
spec.process = configuration.toOCI()
|
||||
@@ -669,21 +664,21 @@ extension LinuxContainer {
|
||||
|
||||
/// Dial a vsock port in the container.
|
||||
public func dialVsock(port: UInt32) async throws -> FileHandle {
|
||||
let state = try self.state.startedState("dialVsock")
|
||||
let state = try self.state.withLock { try $0.startedState("dialVsock") }
|
||||
return try await state.vm.dial(port)
|
||||
}
|
||||
|
||||
/// Close the containers standard input to signal no more input is
|
||||
/// arriving.
|
||||
public func closeStdin() async throws {
|
||||
let state = try self.state.startedState("closeStdin")
|
||||
let state = try self.state.withLock { try $0.startedState("closeStdin") }
|
||||
return try await state.process.closeStdin()
|
||||
}
|
||||
|
||||
/// Relay a unix socket from in the container to the host, or from the host
|
||||
/// to inside the container.
|
||||
public func relayUnixSocket(socket: UnixSocketConfiguration) async throws {
|
||||
let state = try self.state.startedState("relayUnixSocket")
|
||||
let state = try self.state.withLock { try $0.startedState("relayUnixSocket") }
|
||||
|
||||
try await state.vm.withAgent { agent in
|
||||
try await self.relayUnixSocket(
|
||||
|
||||
Reference in New Issue
Block a user