Using NSTask and NSPipe causes 100% CPU usage

百般思念 提交于 2019-12-22 04:39:21

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!