Я успешно читаю из канала из другого потока и печатаю вывод (в окне ncurses, как это происходит).
Мне нужно делать это по одному символу за раз по разным причинам, и я использую select () на FD для конца чтения канала вместе с несколькими другими FD (такими как stdin).
Моя идея состоит в том, чтобы пытаться читать из канала только тогда, когда он неизбежно готов к чтению, предпочтительнее обработки любого ввода. Это, кажется, работает - по крайней мере, для начала. select () устанавливает fd_set, и если FD_ISSET, я выполняю read () из 1 байта из FD. Но select () говорит да, один раз слишком много, и read () блокирует.
Итак, мой вопрос заключается в следующем: почему select () сообщает, что fd готов к чтению, если последующее чтение () блокирует?
(приблизительно) Этот же код работал нормально, когда другой конец канала был подключен к разветвленному процессу, если это помогает.
Я могу опубликовать код по запросу, но это стандарт болота. Установите fd_set, скопируйте его, выберите копию, если FD установлен, вызовите функцию, которая читает байт из того же FD ... в противном случае верните копию fd_set
РЕДАКТИРОВАТЬ: по запросу, вот код:
Настройка моего 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, за исключением того, что этот поток должен периодически делать обновления.