Использование NSTask и NSPipe приводит к 100% загрузке процессора
Я пытаюсь запустить простой скрипт bash с помощью NSTask и направить вывод в текстовое представление. Как только задача выполнена, загрузка моего приложения ЦП составляет 100%, хотя это echo
(теперь).
Я создал совершенно новый проект, чтобы изолировать проблему:
@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
Он правильно выполнен и выводится (как NSData
) зарегистрирован NSLog
:
PipeTest[3933:2623] Read: <74657374 0a>
Однако загрузка процессора остается на уровне 100%, пока я не завершу свое приложение.
РЕДАКТИРОВАТЬ:
Тест Time Profiler возвращает список ниже, но я не уверен, как это интерпретировать.
2 ответа
Дескриптор файла оставлен открытым?
@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];
}
Закрытие файла на NSFileHandle
h
Кажется, чтобы вернуть ваш процессор в нормальное русло.
Предлагаемый код не будет работать, если приложение записывает больше, чем буфер реализации NSFileHandle (4K в моем наблюдении за El Capitan). [h readDataToEndOfFile] имеет тенденцию читать 4K за раз, поэтому этот пример может преждевременно закрыть буфер. Более надежный и одинаково недокументированный подход для вашего обработчика:
NSData *data = [h readDataToEndOfFile];
if (data.length) {
NSLog(@"Read: %@", data);
} else {
[h closeFile];
}