I'm trying to run a simple bash script using NSTask and direct the output to a text view. Once the task is executed, the CPU usage of my app is 100%, even though it's a simple echo
(for now).
I created a completely fresh project to isolate the issue:
@interface AppDelegate ()
@property (nonatomic) NSTask *task;
@property (nonatomic) NSPipe *pipe;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.pipe = [NSPipe pipe];
self.pipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle *h) {
NSLog(@"Read: %@", [h readDataToEndOfFile]);
};
self.task = [[NSTask alloc] init];
self.task.launchPath = @"/bin/bash";
self.task.arguments = @[@"-c", @"echo test"];
self.task.standardOutput = self.pipe;
[self.task launch];
}
@end
It is correctly executed and the output (as an NSData
) is logged with NSLog
:
PipeTest[3933:2623] Read: <74657374 0a>
However the CPU usage stays at 100% until I terminate my app.
EDIT:
A Time Profiler test returns the list below, but I'm not sure how to interpret this.
File handle left open?
@interface AppDelegate ()
@property (nonatomic) NSTask *task;
@property (nonatomic) NSPipe *pipe;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.pipe = [NSPipe pipe];
self.pipe.fileHandleForReading.readabilityHandler = ^(NSFileHandle *h) {
NSLog(@"Read: %@", [h readDataToEndOfFile]);
[h closeFile];
};
self.task = [[NSTask alloc] init];
self.task.launchPath = @"/bin/bash";
self.task.arguments = @[@"-c", @"echo test"];
self.task.standardOutput = self.pipe;
[self.task launch];
}
Closing the file on the NSFileHandle
h
seems to return your CPU usage to normal.
The suggested code would not work if the app writes more than the NSFileHandle's implementation buffer (4K in my observation on El Capitan). [h readDataToEndOfFile] tends to read 4K at a time, so this example may close the buffer prematurely. A more robust and equally undocumented approach for your handler is this one:
NSData *data = [h readDataToEndOfFile];
if (data.length) {
NSLog(@"Read: %@", data);
} else {
[h closeFile];
}
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