NSTask не прекращается - PullRequest
       22

NSTask не прекращается

1 голос
/ 22 января 2011

Я пытаюсь использовать NSTask для запуска UNIX команды apropos.Вот мой код:

NSTask *apropos = [[NSTask alloc] init];
NSPipe *pipe = [[NSPipe alloc] init];
[apropos setLaunchPath:@"/usr/bin/apropos"];
[apropos setArguments:[NSArray arrayWithObjects:@"filename", @"match", nil]];
[apropos setStandardOutput:pipe];
[apropos launch];
[apropos waitUntilExit];

Проблема в том, что это никогда не вернется.Я также попытался использовать пример кода Apple (TaskWrapper), и он возвращает вывод (в трех сегментах), но он никогда не вызывает обработчик processFinished.

Кроме того, обработчик appendOutput: получает дубликаты.Так, например, если apropos возвращает это:

1 2 3 4 5

Я мог бы получить что-то вроде этого:

1 2 3

12 3 4

5

(сгруппированы в 3 добавляемых сообщения).

Замечу, что Apropos отображает вывод в формате, в котором можно прокручивать вверх и вниз вкомандная строка вместо прямого вывода данных прямо на стандартный вывод;как мне надежно прочитать это через NSTask и NSPipe?

Ответы [ 2 ]

3 голосов
/ 22 января 2011

Я только что протестировал эту программу, и она отлично работает: программа завершается, и /tmp/apropos.txt содержит вывод apropos.

#import <Foundation/Foundation.h>

int main()
{
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    NSTask *apropos = [[[NSTask alloc] init] autorelease];
    NSPipe *pipe = [[[NSPipe alloc] init] autorelease];
    NSFileHandle *readHandle = [pipe fileHandleForReading];
    [apropos setLaunchPath:@"/usr/bin/apropos"];
    [apropos setArguments:[NSArray arrayWithObjects:@"filename", @"match", nil]];
    [apropos setStandardOutput:pipe];
    [apropos launch];
    [apropos waitUntilExit];

    NSString *output = [[[NSString alloc]
        initWithData:[readHandle readDataToEndOfFile]
            encoding:NSUTF8StringEncoding] autorelease];

    [output writeToFile:@"/tmp/apropos.txt" atomically:YES
        encoding:NSUTF8StringEncoding error:NULL];

    [pool drain];
    return 0;
}

Вы случайно не используете NSLog() для проверкивыход?Если это так, вам может потребоваться установить канал для stdin, как объяснено в этом моем ответе на вопрос, связанный с NSTask .Кажется, что NSLog() отправка данных на stderr влияет на NSTask.

2 голосов
/ 22 января 2011

С вашим исходным кодом, я думаю, это потому, что вы не читаете вывод команды.Каналы имеют только ограниченный размер буфера, и если вы не прочитаете вывод задачи, он может зависнуть в ожидании освобождения буфера.Я ничего не знаю о примере кода, который вы пробовали, поэтому не могу помочь.Что касается последнего вопроса, apropos использует пейджер, только когда он подключен к терминалу.Вы не эмулируете терминал, поэтому вам не о чем беспокоиться.Вы можете доказать это, запустив apropos whatever | cat в терминале и убедившись, что пейджер не вызывается.

...