Неопределенная ошибка с использованием dup2 для перенаправления stdin и stdout

Я хотел бы использовать каналы для перенаправления stdin и stdout дочернего процесса.

На данный момент у меня есть такой код:

void child(int pipeIn[], int pipeOut[]) {

    char buff[20];
    const char msg[]="Child Message\n";
    close(pipeIn[1]);
    close(pipeOut[0]);

    if (dup2(pipeIn[0], 0))
        perror("dup2 pipeIn");

    if (dup2(pipeOut[1], 1))
        perror("dup2 pipeOut");

    close(pipeIn[0]);
    close(pipeOut[1]);

    for (int i = 0; i < 10; ++i) {
        read(0, buff, 20);
        fprintf(stderr, "Child: %s\n",buff);
        printf("%s",msg);
    }
}

void parent(int pipeIn[], int pipeOut[]) {

    char buff[20];

    const char msg[]="Parent Message\n";
    close(pipeIn[0]);
    close(pipeOut[1]);

    for (int i = 0; i < 10; ++i) {
        write(pipeIn[1], msg, 16);
        read(pipeOut[0], buff, 50);
        printf("Parent: %s", buff);

    }

}

void test() {

    int pipeOut[2],pipeIn[2];

    if(pipe(pipeOut)) {
        perror("pipeOut");
        exit(1);
    }

    if(pipe(pipeIn)) {
        perror("pipeIn");
        exit(1);
    }

    int pid = fork();

    if (pid == -1) {
        perror("fork()");
        exit(1);
    } 
    else if (pid == 0) 
        child(pipeIn, pipeOut);
    else 
        parent(pipeIn,pipeOut);

}

Однако этот код не работает, потому что я продолжаю получать

dup2 pipeOut: неопределенная ошибка: 0

И это заканчивается тупиком.
Я понимаю, что код останавливается, потому что родитель продолжает ждать ответа ребенка (который никогда не приходит), и то же самое, что ребенок продолжает ждать ввода, который никогда не приходит.

Я не понимаю, почему я продолжаю получать эту ошибку. Я делаю что-то неправильно?

Я работаю над MacOS Lion 10.7.2 и Xcode 4.2.1.


ОБНОВЛЕНИЕ: после ответа Адама Розенфилда я исправил свой оператор if. Однако код по-прежнему останавливается, как я уже сказал (я могу прочитать только первое, что выводит ребенок Child: Parent Message, и ничего больше).

Есть идеи, почему это происходит?


person Manlio    schedule 19.03.2012    source источник
comment
Re: update, Используя printf, который по умолчанию буферизирован строкой, вы, вероятно, захотите fflush(stdout) или просто write так же, как и в родительском.   -  person Hasturkun    schedule 19.03.2012
comment
@Hasturkun Спасибо, это помогло! Пожалуйста, оставьте свой комментарий в качестве ответа, и я приму его.   -  person Manlio    schedule 19.03.2012
comment
Вы должны принять ответ Адама Розенфилда, ИМХО, он ответил на ваш первоначальный вопрос. printf вещь довольно второстепенная.   -  person Hasturkun    schedule 19.03.2012


Ответы (1)


dup2(2) в случае успеха возвращает неотрицательное целое число, а именно новый дескриптор файла. В случае ошибки возвращает -1. В вашем случае он возвращает 0 при первом вызове, потому что вы дублируете канал на файловый дескриптор 0.

Чтобы исправить это, измените свои чеки с if(dup2(...)) на if(dup2(...) == -1).

person Adam Rosenfield    schedule 19.03.2012
comment
Вероятно, стоит добавить, что вызовы pipe() в test() имеют ту же проблему. - person FatalError; 19.03.2012
comment
Согласовано. dup2 возвращает второй дескриптор файла в случае успеха и отрицательное значение в случае ошибки. Лично я предпочитаю if (dup2(..) < 0) :) - person Jinghao Shi; 19.03.2012
comment
Спасибо, вы правы (+1). Однако, как я уже сказал, код по-прежнему останавливается ... Есть предложения, почему это происходит? - person Manlio; 19.03.2012