select () возвращает недопустимый аргумент

Я успешно читаю из канала из другого потока и распечатываю вывод (в окне ncurses, как это происходит) .

Мне нужно делать это по одному символу за раз по разным причинам, и я использую select () в FD для чтения конца канала вместе с несколькими другими FD (например, stdin).

Моя идея состоит в том, чтобы пытаться читать из канала только тогда, когда он неизбежно готов к чтению, а не обрабатывать любой ввод. Кажется, это работает - по крайней мере, для начала. select () устанавливает fd_set, и если FD_ISSET, я выполняю чтение () 1 байта из FD. Но select () говорит «да» один раз слишком много, и read () блокируется.

Итак, мой вопрос - зачем select () сообщать, что fd готов к чтению, если последующее чтение () блокируется?

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

Я могу опубликовать код по запросу, но это стандартная проблема. Настройте fd_set, скопируйте его, выберите копию, если FD установлен, вызовите функцию, которая читает байт из того же FD ... в противном случае отмените копию fd_set

EDIT: по запросу, вот код:

Настройка моего fd_set:

fd_set fds;
FD_ZERO(&fds); 
FD_SET(interp_output[0], &fds);
FD_SET(STDIN_FILENO, &fds);
struct timeval timeout, tvcopy; timeout.tv_sec=1;
int maxfd=interp_output[0]+1; //always >stdin+1
fd_set read_fds;
FD_COPY(&fds, &read_fds);

В цикле:

if (select(maxfd, &read_fds, NULL, NULL, &timeout)==-1) {perror("couldn't select"); return;}
if (FD_ISSET(interp_output[0], &read_fds)) {
    handle_interp_out();
} else if (FD_ISSET(STDIN_FILENO, &read_fds)) {
//waddstr(cmdwin, "stdin!"); wrefresh(cmdwin);
    handle_input();
}

FDCOPY(&fds, &read_fds);

handle_interp_out ():

void handle_interp_out() {
    int ch;
    read(interp_output[0], &ch, 1);
    if (ch>0) {
            if (ch=='\n') { if (cmd_curline>=cmdheight) cmdscroll(); wmove(cmdwin, ++cmd_curline, 1); }
            else waddch(cmdwin, ch);
            wrefresh(cmdwin);
    }
}

РЕДАКТИРОВАТЬ 2: Код записи - это просто fprintf в ФАЙЛЕ *, открытом с помощью fdopen (interp_output [1], "w" ) - это в другой ветке. Все, что я получаю, это моя "подсказка>" - она ​​все это правильно печатает, но делает еще одну итерацию, которой не следовало бы. Я отключил буферизацию, что доставляло мне другие проблемы.

РЕДАКТИРОВАТЬ 3: Это стало проблемой при моем вызове select (). Похоже, что он сразу же возвращает -1, а для errno устанавливается значение «недопустимый аргумент». Read () не знает этого и просто продолжает работать. Что может быть не так с моим select ()? Я обновил код и изменил заголовок, чтобы более точно отразить проблему ...

РЕДАКТИРОВАТЬ 4: Итак, теперь я полностью запутался. Значение тайм-аута .tv_sec = 1 почему-то не годится. Избавившись от него, код работает нормально. Если у кого-то есть теории, я весь в ушах. Я бы просто оставил его на NULL, за исключением того, что этому потоку необходимо периодически делать обновления.

6
задан Robert 6 December 2010 в 17:39
поделиться