objective-cmacoscocoanstasknspipe

Using NSTask and NSPipe causes 100% CPU usage


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


Solution

  • 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.