diff --git a/Foundation/FileHandle.swift b/Foundation/FileHandle.swift index 2f31d44e72..663c13fb43 100644 --- a/Foundation/FileHandle.swift +++ b/Foundation/FileHandle.swift @@ -8,6 +8,7 @@ // import CoreFoundation +import Dispatch #if os(OSX) || os(iOS) import Darwin @@ -345,7 +346,19 @@ extension FileHandle { } open func waitForDataInBackgroundAndNotify() { - NSUnimplemented() + let global = DispatchQueue.global(qos: .background) + let channel = DispatchIO(type: .stream, fileDescriptor: fileDescriptor, queue: global) { _ in } + + // The desire is to trigger the handler blocka as soon as there is any data in the channel. + channel.setLimit(lowWater: 1) + + channel.read(offset: 0, length: Int.max, queue: global) { (_, _, error) in + var notification = Notification(name: .NSFileHandleDataAvailable, object: nil, userInfo: nil) + if error != 0 { + notification.userInfo = ["NSFileHandleError": NSNumber(value: error)] + } + NotificationCenter.default.post(notification) + } } open var readabilityHandler: ((FileHandle) -> Void)? { diff --git a/TestFoundation/TestFileHandle.swift b/TestFoundation/TestFileHandle.swift index 1b389ff0f7..8776a38145 100644 --- a/TestFoundation/TestFileHandle.swift +++ b/TestFoundation/TestFileHandle.swift @@ -21,6 +21,7 @@ class TestFileHandle : XCTestCase { ("test_constants", test_constants), ("test_pipe", test_pipe), ("test_nullDevice", test_nullDevice), + ("test_waitForDataInBackgroundAndNotify", test_waitForDataInBackgroundAndNotify), ] } @@ -64,4 +65,21 @@ class TestFileHandle : XCTestCase { fh.seek(toFileOffset: 0) XCTAssertEqual(fh.readDataToEndOfFile().count, 0) } + + func test_waitForDataInBackgroundAndNotify() { + let expect = expectation(description: "Receiving asynchronous data from pipe") + let pipe = Pipe() + pipe.fileHandleForReading.waitForDataInBackgroundAndNotify() + + NotificationCenter.default.addObserver(forName: .NSFileHandleDataAvailable, object: nil, queue: nil) { (notification) in + XCTAssertEqual(notification.name, .NSFileHandleDataAvailable) + XCTAssertNil(notification.userInfo) + expect.fulfill() + } + + let data = Data(bytes: [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]) + pipe.fileHandleForWriting.write(data) + + waitForExpectations(timeout: 2) + } }