Опрос работает на stdin при вводе вручную, но не при вводе по конвейеру и не перенаправляется
Рассмотрим эту программу на C:
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
#define TIMEOUT 500 // 0.5 s
#define BUF_SIZE 512
int fd_can_read(int fd, int timeout) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout)) {
if (pfd.revents & POLLIN) {
return 1;
}
}
return 0;
}
int main(int argv, char **argc) {
int fd;
size_t bytes_read;
char buffer[BUF_SIZE];
fd = STDIN_FILENO;
while (1) {
if (fd_can_read(fd, TIMEOUT)) {
printf("Can read\n");
bytes_read = read(fd, buffer, sizeof(buffer));
printf("Bytes read: %zu\n", bytes_read);
}
else {
printf("Can't read\n");
}
}
}
Он пытается опрашивать заданный дескриптор файла (в данном случае это fd stdin) и пытается прочитать его, когда он будет доступен для чтения. Вот пример входного файла с именем "input":
stuff to be read
Допустим, я запускаю программу, даю несколько входных данных и закрываю ее:
./a.out
test
Can read
Bytes read: 5
Can't read
Can't read
...
Итак, давайте попробуем прочитать входные данные из файла, перенаправив содержимое этого файла на stdin
моей программы:
cat input | ./a.out # Or ./a.out < input
Bytes read: 0
Can read
Bytes read: 0
Can read
...
Теперь опрос возвращается мгновенно (не дожидается истечения времени ожидания) и дает результаты, которых я не ожидал. я знаю poll()
неправильно работает с файлами, но если я не ошибаюсь, я не читаю из файла.
1 ответ
Проблема в том, что poll
(как select
) только скажу, что звонок на например read
не будет блокировать. Он не говорит вам, есть ли на самом деле что-нибудь для чтения.
И если вы читаете read
Страница справочника вы увидите, что когда он вернется 0
это означает конец файла (или соединение закрыто для сокетов).
Какие poll
говорит вам, что read
можно назвать без блокировки, а что read
говорит вам, возвращаясь 0
в том, что больше нечего читать.
Вы получите аналогичное "ложное срабатывание", нажав сочетание клавиш "конец файла" (по умолчанию Ctrl-D в системах POSIX, таких как Linux) для примера ввода без переадресации или с переадресацией.