问题
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.
回答1:
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.
回答2:
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];
}
来源:https://stackoverflow.com/questions/13747232/using-nstask-and-nspipe-causes-100-cpu-usage