Skip to content

Commit bec1008

Browse files
authored
VsockConnectionStream: Conform to AsyncSequence (#380)
I didn't like how we expose the asyncstream via a public connections field. We should have the type conform to AsyncSequence and then hide the underlying stream. This also stops listening on the stdio ports after we get the initial connection.
1 parent 8b39713 commit bec1008

File tree

3 files changed

+24
-7
lines changed

3 files changed

+24
-7
lines changed

Sources/Containerization/LinuxProcess.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,21 @@ public final class LinuxProcess: Sendable {
119119
extension LinuxProcess {
120120
func setupIO(streams: [VsockConnectionStream?]) async throws -> [FileHandle?] {
121121
let handles = try await Timeout.run(seconds: 3) {
122-
await withTaskGroup(of: (Int, FileHandle?).self) { group in
122+
try await withThrowingTaskGroup(of: (Int, FileHandle?).self) { group in
123123
var results = [FileHandle?](repeating: nil, count: 3)
124124

125125
for (index, stream) in streams.enumerated() {
126126
guard let stream = stream else { continue }
127127

128128
group.addTask {
129-
let first = await stream.connections.first(where: { _ in true })
129+
let first = await stream.first(where: { _ in true })
130+
stream.finish()
131+
try self.vm.stopListen(stream.port)
130132
return (index, first)
131133
}
132134
}
133135

134-
for await (index, fileHandle) in group {
136+
for try await (index, fileHandle) in group {
135137
results[index] = fileHandle
136138
}
137139
return results

Sources/Containerization/UnixSocketRelay.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ extension SocketRelay {
201201
$0.t = Task {
202202
do {
203203
defer { connectionStream.finish() }
204-
for await connection in connectionStream.connections {
204+
for await connection in connectionStream {
205205
try await self.handleGuestVsockConn(
206206
vsockConn: connection,
207207
hostConnectionPath: hostPath,

Sources/Containerization/VsockConnectionStream.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import Virtualization
2121
#endif
2222

2323
/// A stream of vsock connections.
24-
public final class VsockConnectionStream: NSObject, Sendable {
24+
public final class VsockConnectionStream: NSObject, Sendable, AsyncSequence {
25+
public typealias Element = FileHandle
26+
2527
/// A stream of connections dialed from the remote.
26-
public let connections: AsyncStream<FileHandle>
28+
private let connections: AsyncStream<FileHandle>
2729
/// The port the connections are for.
2830
public let port: UInt32
2931

@@ -39,6 +41,10 @@ public final class VsockConnectionStream: NSObject, Sendable {
3941
public func finish() {
4042
self.cont.finish()
4143
}
44+
45+
public func makeAsyncIterator() -> AsyncStream<FileHandle>.AsyncIterator {
46+
connections.makeAsyncIterator()
47+
}
4248
}
4349

4450
#if os(macOS)
@@ -49,9 +55,18 @@ extension VsockConnectionStream: VZVirtioSocketListenerDelegate {
4955
from _: VZVirtioSocketDevice
5056
) -> Bool {
5157
let fd = dup(conn.fileDescriptor)
58+
guard fd != -1 else {
59+
return false
60+
}
5261
conn.close()
5362

54-
cont.yield(FileHandle(fileDescriptor: fd, closeOnDealloc: false))
63+
let fh = FileHandle(fileDescriptor: fd, closeOnDealloc: false)
64+
let result = cont.yield(fh)
65+
if case .terminated = result {
66+
try? fh.close()
67+
return false
68+
}
69+
5570
return true
5671
}
5772
}

0 commit comments

Comments
 (0)