2012-12-06 15 views
7

Ich versuche, ein einfaches Bash-Skript mit NSTask auszuführen und die Ausgabe in eine Textansicht zu leiten. Sobald die Aufgabe ausgeführt wird, ist die CPU-Auslastung meiner App 100%, obwohl es eine einfache echo (für jetzt) ​​ist.Verwendung von NSTask und NSPipe verursacht 100% CPU-Auslastung

ich ein völlig neues Projekt erstellt, das Problem zu isolieren:

@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 

Es korrekt ausgeführt wird und die Ausgabe (als NSData) mit NSLog protokolliert:

PipeTest[3933:2623] Read: <74657374 0a> 

jedoch die CPU-Auslastung bleibt bei 100%, bis ich meine App beende.

EDIT:

A Time Profiler-Test gibt die Liste unten, aber ich bin nicht sicher, wie dies zu interpretieren.

enter image description here

Antwort

9

Datei Griff offen gelassen?

@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]; 
} 

Schließen der Datei auf dem NSFileHandleh scheint die CPU-Auslastung normalisieren.

+1

Das ist großartig, danke! Kannst du auch erklären, warum * die CPU so auf offene Dateigriffe reagiert? –

2

Der vorgeschlagene Code würde nicht funktionieren, wenn die App mehr als den Implementierungspuffer der NSFileHandle schreibt (4K in meiner Beobachtung auf El Capitan). [h readDataToEndOfFile] tendiert dazu, jeweils 4K zu lesen, daher kann dieses Beispiel den Puffer vorzeitig schließen. Ein robusterer und ebenso undokumentierter Ansatz für Ihren Handler ist dieser:

NSData *data = [h readDataToEndOfFile]; 
if (data.length) { 
    NSLog(@"Read: %@", data); 
} else { 
    [h closeFile]; 
}