mirror of
https://github.com/cirruslabs/tart.git
synced 2026-09-30 03:01:12 +02:00
ControlSocket: duplicate VirtIO socket connection's file descriptor (#1333)
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import Foundation
|
||||
import Darwin
|
||||
import System
|
||||
import Virtualization
|
||||
import Network
|
||||
import os.log
|
||||
import NIO
|
||||
@@ -72,7 +75,13 @@ class ControlSocket {
|
||||
|
||||
self.logger.info("running control socket proxy")
|
||||
|
||||
let vmChannel = try await ClientBootstrap(group: eventLoopGroup).withConnectedSocket(vmConnection.fileDescriptor) { childChannel in
|
||||
// Duplicate the connection's file descriptor
|
||||
//
|
||||
// This way VZVirtioSocketConnection and NIO won't race to close the same descriptor,
|
||||
// which may result in "tart run" crashing because of NIO's fatal assertion on EBADF.
|
||||
let vmSocket = try duplicateAndCloseConnection(vmConnection)
|
||||
|
||||
let vmChannel = try await ClientBootstrap(group: eventLoopGroup).withConnectedSocket(vmSocket) { childChannel in
|
||||
childChannel.eventLoop.makeCompletedFuture {
|
||||
try NIOAsyncChannel<ByteBuffer, ByteBuffer>(
|
||||
wrappingChannelSynchronously: childChannel
|
||||
@@ -104,4 +113,15 @@ class ControlSocket {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func duplicateAndCloseConnection(_ connection: VZVirtioSocketConnection) throws -> CInt {
|
||||
defer { connection.close() }
|
||||
|
||||
let fd = fcntl(connection.fileDescriptor, F_DUPFD_CLOEXEC, 0)
|
||||
guard fd >= 0 else {
|
||||
throw Errno(rawValue: errno)
|
||||
}
|
||||
|
||||
return fd
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user