Skip to content

Commit e098576

Browse files
committed
Fix possible ObjC exception on old (Apple) OSes
1 parent dc5daf5 commit e098576

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

Sources/CLTLogger.swift

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ public struct CLTLogger : LogHandler {
175175
/* We compute the data to print outside of the lock. */
176176
let data = Self.format(message: message.description, flatMetadata: effectiveFlatMetadata, multilineMode: multilineMode, constants: constants)
177177

178-
Self.write(data, to: outputFileHandle)
178+
Self.writeLog(data, to: outputFileHandle)
179179
}
180180

181181
/** Writes to the given file descriptor like the logger would. */
182-
public static func write(_ data: Data, to fh: FileHandle) {
182+
public static func writeLog(_ data: Data, to fh: FileHandle) {
183183
/* We lock, because the writeAll function might split the write in more than 1 write
184184
* (if the write system call only writes a part of the data).
185185
* If another part of the program writes to the file descriptor, we might get interleaved data,
@@ -189,17 +189,28 @@ public struct CLTLogger : LogHandler {
189189
/* Is the write retried on interrupt?
190190
* We’ll assume yes, but we don’t and can’t know for sure
191191
* until FileHandle has been migrated to the open-source Foundation. */
192-
if #available(macOS 10.15.4, iOS 13.4, tvOS 13.4, watchOS 6.2, *) {
193-
#if swift(>=5.2) || (!os(macOS) && !os(iOS) && !os(tvOS) && !os(watchOS))
192+
#if canImport(Darwin)
193+
if #available(macOS 10.15.4, tvOS 13.4, iOS 13.4, watchOS 6.2, *) {
194194
_ = try? fh.write(contentsOf: data)
195-
#else
196-
/* Note: This throws an actual objc exception if it fails. */
197-
fh.write(data)
198-
#endif
199195
} else {
200-
/* Note: This throws an actual objc exception if it fails. */
201-
fh.write(data)
196+
/* Let’s write “manullay” (FileHandle’s write(_:) method throws an ObjC exception in case of an error. */
197+
data.withUnsafeBytes{ bytes in
198+
guard !bytes.isEmpty else {
199+
return
200+
}
201+
var written: Int = 0
202+
repeat {
203+
written += write(
204+
fh.fileDescriptor,
205+
bytes.baseAddress!.advanced(by: written),
206+
bytes.count - written
207+
)
208+
} while written < bytes.count && (errno == EINTR || errno == EAGAIN)
209+
}
202210
}
211+
#else
212+
_ = try? fh.write(contentsOf: data)
213+
#endif
203214
}
204215
}
205216

Tests/CLTLoggerTests/CLTLoggerTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ final class CLTLoggerTests : XCTestCase {
6868
var logger = Logger(label: "my logger")
6969
logger.logLevel = .trace
7070

71-
CLTLogger.write(Data("\n".utf8), to: .standardError)
71+
CLTLogger.writeLog(Data("\n".utf8), to: .standardError)
7272

7373
logger.trace( "trace: Example of a log at this level. Isn’t it amazing?")
7474
logger.debug( "debug: Example of a log at this level. Isn’t it amazing?")
@@ -78,11 +78,11 @@ final class CLTLoggerTests : XCTestCase {
7878
logger.error( "error: Example of a log at this level. Isn’t it amazing?")
7979
logger.critical("critical: Example of a log at this level. Isn’t it amazing?")
8080

81-
CLTLogger.write(Data("\n".utf8), to: .standardError)
81+
CLTLogger.writeLog(Data("\n".utf8), to: .standardError)
8282

8383
logger.info("An informational message with metadata.", metadata: ["component": "LoggerTester", "array-value": .array(["1", "2", "3"]), "dictionary-value": .dictionary(["key1": "value1", "key2": "value2", "key3": "value3"])])
8484

85-
CLTLogger.write(Data("\n".utf8), to: .standardError)
85+
CLTLogger.writeLog(Data("\n".utf8), to: .standardError)
8686
}
8787

8888
func testVisual3() {

0 commit comments

Comments
 (0)