NSConcreteFileHandle.availableData “occasionally” blocks upon a NSFileHandleDataAvailable notification

MacOS:

10.12.6 (16G29)


SDK:

Xcode 9 beta 4

Trying to debug an "Application Not Responding" for a macOS app that I've written.

Here is a sample that I gathered. Assuming I am reading this correctly, the main thread is blocked while trying to read the available data,

i.e. NSConcreteFileHandle availableData


The documetation states,

> this method reads up to a buffer of data and returns it; if no data is available, the method blocks.


I struggle to see how that's possible, given that the block is executed on the NSFileHandleDataAvailable notification.


A related code sample does not look any different to me eyes. Found a related post from 2003, http://idevapps.com/forum/showthread.php?tid=2793, but no solution. Another one from 2012, https://stackoverflow.com/a/12108291/3887.


A list of open files (output reduced for clarity) shows indeed the pipe with a size

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

bash 99437 qnoid 1 PIPE 0x23cb7cc5248961db 65536 ->0x23cb7cc524896ddb

and offset

COMMAND PID USER FD TYPE DEVICE OFFSET NODE NAME

bash 99437 qnoid 1 PIPE 0x23cb7cc5248961db 0t0 ->0x23cb7cc524896ddb


extension Process {

    func windmill_waitForDataInBackground(_ pipe: Pipe, callback: @escaping (_ data: String, _ count: Int) -> Void) {
        pipe.fileHandleForReading.waitForDataInBackgroundAndNotify()

        NotificationCenter.default.addObserver(forName: .NSFileHandleDataAvailable, object: pipe.fileHandleForReading , queue: OperationQueue.main) { notification in

            guard let fileHandleForReading = notification.object as? FileHandle else {
                return
            }

            guard case let availableData = fileHandleForReading.availableData, availableData.count != 0 else {
                return
            }

            let availableString = String(data: availableData, encoding: .utf8) ?? ""

            callback(availableString, availableData.count)
            fileHandleForReading.waitForDataInBackgroundAndNotify()
        }
    }
}