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