mirror of https://github.com/cirruslabs/tart.git
Use an owning Softnet control file handle
This commit is contained in:
parent
311eec95f4
commit
4a018ce4bb
|
|
@ -13,21 +13,20 @@ class Softnet: Network {
|
|||
private let process = Process()
|
||||
private var monitorTask: Task<Void, Error>? = nil
|
||||
private let monitorTaskFinished = ManagedAtomic<Bool>(false)
|
||||
private var controlFD: Int32?
|
||||
|
||||
let vmFD: Int32
|
||||
|
||||
init(vmMACAddress: String, extraArguments: [String] = [], controlFD: Int32? = nil) throws {
|
||||
if let controlFD = controlFD {
|
||||
do {
|
||||
try Self.validateControlFD(controlFD)
|
||||
} catch {
|
||||
close(controlFD)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
var controlFileHandle: FileHandle?
|
||||
|
||||
self.controlFD = controlFD
|
||||
if let controlFD = controlFD {
|
||||
guard controlFD > STDERR_FILENO else {
|
||||
throw SoftnetError.InitializationFailed(why: "Softnet control file descriptor must be greater than 2")
|
||||
}
|
||||
|
||||
controlFileHandle = FileHandle(fileDescriptor: controlFD, closeOnDealloc: true)
|
||||
try Self.validateControlFD(controlFD)
|
||||
}
|
||||
|
||||
let fds = UnsafeMutablePointer<Int32>.allocate(capacity: MemoryLayout<Int>.stride * 2)
|
||||
|
||||
|
|
@ -46,16 +45,12 @@ class Softnet: Network {
|
|||
process.arguments = ["--vm-fd", String(STDIN_FILENO), "--vm-mac-address", vmMACAddress] + extraArguments
|
||||
process.standardInput = FileHandle(fileDescriptor: softnetFD, closeOnDealloc: false)
|
||||
|
||||
if let controlFD = controlFD {
|
||||
if let controlFileHandle = controlFileHandle {
|
||||
process.arguments! += ["--control-fd", String(STDOUT_FILENO)]
|
||||
process.standardOutput = FileHandle(fileDescriptor: controlFD, closeOnDealloc: false)
|
||||
process.standardOutput = controlFileHandle
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
closeControlFD()
|
||||
}
|
||||
|
||||
static func validateControlFD(_ fd: Int32) throws {
|
||||
guard fd > STDERR_FILENO else {
|
||||
throw SoftnetError.InitializationFailed(why: "Softnet control file descriptor must be greater than 2")
|
||||
|
|
@ -100,7 +95,7 @@ class Softnet: Network {
|
|||
}
|
||||
|
||||
func run(_ sema: AsyncSemaphore) throws {
|
||||
defer { closeControlFD() }
|
||||
defer { try? (process.standardOutput as? FileHandle)?.close() }
|
||||
|
||||
try process.run()
|
||||
|
||||
|
|
@ -116,13 +111,6 @@ class Softnet: Network {
|
|||
}
|
||||
}
|
||||
|
||||
private func closeControlFD() {
|
||||
if let controlFD = controlFD {
|
||||
close(controlFD)
|
||||
self.controlFD = nil
|
||||
}
|
||||
}
|
||||
|
||||
func stop() async throws {
|
||||
if monitorTaskFinished.load(ordering: .sequentiallyConsistent) {
|
||||
// Consume the monitor task's value to ensure the task has finished
|
||||
|
|
|
|||
|
|
@ -51,6 +51,16 @@ final class SoftnetControlFDTests: XCTestCase {
|
|||
XCTAssertThrowsError(try Softnet.validateControlFD(STDERR_FILENO))
|
||||
}
|
||||
|
||||
func testStandardDescriptorsRemainOpenWhenInitializationFails() throws {
|
||||
for fd in [STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO] {
|
||||
let flags = fcntl(fd, F_GETFD)
|
||||
XCTAssertNotEqual(flags, -1)
|
||||
|
||||
XCTAssertThrowsError(try Softnet(vmMACAddress: "02:00:00:00:00:01", controlFD: fd))
|
||||
XCTAssertEqual(fcntl(fd, F_GETFD), flags)
|
||||
}
|
||||
}
|
||||
|
||||
func testControlChannelIsPassedToSoftnetAndVMFDRemainsDatagram() async throws {
|
||||
let temporaryDirectory = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
|
||||
try FileManager.default.createDirectory(at: temporaryDirectory, withIntermediateDirectories: false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue