문제

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.

enter image description here

도움이 되었습니까?

해결책

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];
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top