I'm attempting to read data from the Standard Error of a NSTask in Cocoa using waitForDataInBackgroundAndNotify. The following code does read the stream, so it's already working partially.
The problem I have is that sometimes the NSFileHandleDataAvailableNotification starts firing repeatedly (thousands of times per second) with no new data at all ([data length] returns 0). My process then starts using a lot of CPU, slowing the machine to a halt. Has any of you guys hit something like this before in the past? Thanks in advance.
/**
* Start reading from STDERR
*
* @private
*/
- (void)startReadingStandardError {
NSFileHandle *fileHandle = [_task.standardError fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(errorData:)
name:NSFileHandleDataAvailableNotification
object:fileHandle];
[fileHandle waitForDataInBackgroundAndNotify];
}
/**
* Fired whenever new data becomes available on STDERR
*
* @private
*/
-(void) errorData: (NSNotification *) notification
{
NSFileHandle *fileHandle = (NSFileHandle*) [notification object];
NSData *data = [fileHandle availableData];
if ([data length]) {
// consume data
}
[fileHandle waitForDataInBackgroundAndNotify];
}
So, ended up figuring it out by myself. According to the NSFileHandle Class Reference, if the NSData object returned by availableData has a length of 0, it means that the end-of-file has been reached. I was not handling this case correctly. This fixed it for me:
/**
* Fired whenever new data becomes available on STDERR
*
* @private
*/
-(void) errorData: (NSNotification *) notification
{
NSFileHandle *fileHandle = (NSFileHandle*) [notification object];
NSData *data = [fileHandle availableData];
if ([data length]) {
// consume data
// ...
[fileHandle waitForDataInBackgroundAndNotify];
} else {
// EOF was hit, remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleDataAvailableNotification object:fileHandle];
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With