select() не возвращается после тайм-аута

Я создаю один исполняемый файл с именем «readmsg». Его исходный код приведен ниже. select() работает, если я выполняю только readmsg в оболочке (я вижу вывод timeout).

Но если я создам файл FIFO с помощью команды: mknod /tmp/message p и выполню readmsg < /tmp/message в оболочке. В результате select() не может вернуться, если я что-то не напишу в /tmp/message. Мой вопрос: почему я не могу получить вывод timeout?

исходный код "readmsg":

    #define STDIN 0
    fd_set fds;
    struct timeval tv;
    while (1) {
        FD_ZERO(&fds);
        FD_SET(STDIN, &fds);
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        ret = select(STDIN + 1, &fds, NULL, NULL, &tv);
        if (ret > 0) {
            printf("works\n");
            if (FD_ISSET(STDIN, &fds)) {
                // read ...
            }
        } else if (ret == 0) {
            printf("timeout!!\n");
        } else {
            printf("interrupt\n");
        }
    }

person Tody.Lu    schedule 13.01.2013    source источник
comment
С каналом вы, вероятно, не доберетесь до выбора в первую очередь. Поместите еще несколько распечаток отладки перед выбором.   -  person Mat    schedule 13.01.2013
comment
Вы должны напечатать errno, например. замените последний printf на printf("failed - %s\n", strerror(errno));; и вы должны предпочесть poll вместо select (например, потому что select ограничивает максимальное количество файловых дескрипторов до размера fd_set; Google для C10K проблема для получения дополнительной информации).   -  person Basile Starynkevitch    schedule 13.01.2013
comment
Вам повезло, что вы работаете в Linux, а не в Solaris. ужас кодирования. ком/блог/2008/03/ :)   -  person emil    schedule 13.01.2013
comment
Кроме того, вы можете strace и свою программу, и программы, записывающие в FIFO....   -  person Basile Starynkevitch    schedule 13.01.2013
comment
Я предполагаю, что оболочка блокируется при открытии fifo для перенаправления. Без O_NONBLOCK open() будет блокироваться, если никто не открыл fifo для записи.   -  person Martin R    schedule 13.01.2013


Ответы (1)


Спасибо @Mat. После добавления printf() рядом с main() тоже не выводится. Даже нет идентификатора процесса readmsg при выполнении ps. Таким образом, это доказывает, что процесс readmsg < /tmp/message заблокирован до того, как FIFO будет готов к записи.

Нет никакой ошибки. Фактически, readmsg хорошо работает при чтении сообщений из перенаправленного файла FIFO.

person Tody.Lu    schedule 13.01.2013