Skip to content

Commit 5d5a4a1

Browse files
committed
Make the back channel property in ExitTest a onceler rather than a function so you can't break things by calling it twice in the same process
1 parent 13ab832 commit 5d5a4a1

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,19 @@ public struct ExitTest: Sendable {
6666
#endif
6767
}
6868

69-
/// Find a back channel file handle set up by the parent process.
69+
/// The back channel file handle set up by the parent process.
7070
///
71-
/// - Returns: A file handle open for writing to which events should be
72-
/// written, or `nil` if the file handle could not be resolved.
73-
private static func _findBackChannel() -> FileHandle? {
71+
/// The value of this property is a file handle open for writing to which
72+
/// events should be written, or `nil` if the file handle could not be
73+
/// resolved.
74+
private static let _backChannel: FileHandle? = {
7475
guard let backChannelEnvironmentVariable = Environment.variable(named: "SWT_EXPERIMENTAL_BACKCHANNEL") else {
7576
return nil
7677
}
7778

7879
var fd: CInt?
7980
#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD)
80-
fd = CInt(backChannelEnvironmentVariable).map(dup)
81+
fd = CInt(backChannelEnvironmentVariable)
8182
#elseif os(Windows)
8283
if let handle = UInt(backChannelEnvironmentVariable).flatMap(HANDLE.init(bitPattern:)) {
8384
fd = _open_osfhandle(Int(bitPattern: handle), _O_WRONLY | _O_BINARY)
@@ -90,7 +91,7 @@ public struct ExitTest: Sendable {
9091
}
9192

9293
return try? FileHandle(unsafePOSIXFileDescriptor: fd, mode: "wb")
93-
}
94+
}()
9495

9596
/// Call the exit test in the current process.
9697
///
@@ -104,23 +105,22 @@ public struct ExitTest: Sendable {
104105

105106
// Set up the configuration for this process.
106107
var configuration = Configuration()
107-
if let backChannel = Self._findBackChannel() {
108-
// Encode events as JSON and write them to the back channel file handle.
109-
var eventHandler = ABIv0.Record.eventHandler(encodeAsJSONLines: true) { json in
110-
try? backChannel.write(json)
111-
}
112108

113-
// Only forward issue-recorded events. (If we start handling other kinds
114-
// of event in the future, we can forward them too.)
115-
eventHandler = { [eventHandler] event, eventContext in
116-
if case .issueRecorded = event.kind {
117-
eventHandler(event, eventContext)
118-
}
119-
}
109+
// Encode events as JSON and write them to the back channel file handle.
110+
var eventHandler = ABIv0.Record.eventHandler(encodeAsJSONLines: true) { json in
111+
try? Self._backChannel?.write(json)
112+
}
120113

121-
configuration.eventHandler = eventHandler
114+
// Only forward issue-recorded events. (If we start handling other kinds
115+
// of event in the future, we can forward them too.)
116+
eventHandler = { [eventHandler] event, eventContext in
117+
if case .issueRecorded = event.kind {
118+
eventHandler(event, eventContext)
119+
}
122120
}
123121

122+
configuration.eventHandler = eventHandler
123+
124124
do {
125125
try await Configuration.withCurrent(configuration, perform: body)
126126
} catch {

0 commit comments

Comments
 (0)