Don't ignore possible errors from dup(2) (#382)

Everytime we grab a vsock connection we dup the conn and close the
original, otherwise we'd need to carry around the vsock connection type
everywhere as it closes the fd in its destructor. We weren't checking
the return value of dup however, so if it did fail we'd have a useless
filehandle with an fd of -1.
This commit is contained in:
Danny Canter
2025-11-06 15:48:02 -08:00
committed by GitHub
parent 52ed5b542c
commit 619354ef74
2 changed files with 39 additions and 14 deletions
@@ -139,8 +139,11 @@ extension VZVirtualMachine {
}
extension VZVirtioSocketConnection {
func dupHandle() -> FileHandle {
func dupHandle() throws -> FileHandle {
let fd = dup(self.fileDescriptor)
if fd == -1 {
throw POSIXError.fromErrno()
}
self.close()
return FileHandle(fileDescriptor: fd, closeOnDealloc: false)
}
@@ -195,25 +195,47 @@ extension VZVirtualMachineInstance: VirtualMachineInstance {
public func dialAgent() async throws -> Vminitd {
try await lock.withLock { connections in
let handle = try await vm.connect(
queue: queue,
port: Vminitd.port
).dupHandle()
do {
let conn = try await vm.connect(
queue: queue,
port: Vminitd.port
)
let handle = try conn.dupHandle()
let agent = Vminitd(connection: handle, group: self.group)
connections.agents.append(agent)
let agent = Vminitd(connection: handle, group: self.group)
connections.agents.append(agent)
return agent
return agent
} catch {
if let err = error as? ContainerizationError {
throw err
}
throw ContainerizationError(
.internalError,
message: "failed to dial agent",
cause: error
)
}
}
}
func dial(_ port: UInt32) async throws -> FileHandle {
try await lock.withLock { connections in
let handle = try await vm.connect(
queue: queue,
port: port
).dupHandle()
return handle
do {
let conn = try await vm.connect(
queue: queue,
port: port
)
return try conn.dupHandle()
} catch {
if let err = error as? ContainerizationError {
throw err
}
throw ContainerizationError(
.internalError,
message: "failed to dial vsock port",
cause: error
)
}
}
}