Как убедиться, что все выходные данные на конвейере с асинхронным вводом-выводом завершены перед закрытием - PullRequest
2 голосов
/ 22 ноября 2011

Я использую канал, чтобы прочитать вывод функции, передав ей дескриптор файла. Для асинхронного чтения выходных данных я устанавливаю конец канала «чтение» в режиме ASYNC NON BLOCKING и настраиваю обработчик ввода-вывода с помощью SIGACTION. Мой код выглядит следующим образом:

struct sigaction io_act;
struct sigaction io_act_old;
sigset_t block_mask;

/* create the pipe */    
pipe (pipe_fd);

/* set the reading end of pipe in ASYNC mode */
fcntl (pipe_fd[0], F_SETOWN, getpid());
fcntl (pipe_fd[0], F_SETFL, O_ASYNC | O_NONBLOCK);

/* add an I/O handler for SIGIO */
sigemptyset (&block_mask);
io_act.sa_handler = sigio_handler;
io_act.sa_mask = block_mask;
io_act.sa_flags = SA_RESTART;
sigaction (SIGIO, &io_act, &io_act_old);

/* executing the function that generate output in given FILEDES */
my_generate_output (pipe_fd[1]);

close(pipe_fd[1]);

/* this sleep should not be needed (subject of question) */
sleep(1);
close (pipe_fd[0]);

/* restore previous signal handler */
sigaction (SIGIO, &io_act_old, NULL);

Проблема в том, что если я пропущу вызов функции ожидания, я могу закрыть канал и отключить обработчик SIGIO до завершения вывода. Следствием этого является то, что приложение прерывается из-за необработанного сигнала SIGIO (сообщение «Возможен ввод / вывод»).

Как я могу убедиться, что весь вывод был прочитан из канала перед отключением обработчика SIGIO?

Ответы [ 2 ]

0 голосов
/ 22 ноября 2011

Чтобы получить количество читаемых байтов, вы можете использовать ioctl FIONREAD, который не очень переносим.См. этот вопрос в качестве надуманного примера.

Вы также можете проверить наличие вещей для чтения с помощью poll , select и друзей.

И состояние конца файла сообщается с read, возвращающим 0 в качестве счетчика.

ADDENDA

согласно read (2) Справочная страница syscall, read завершается неудачно с ошибкой ==:

   EAGAIN or EWOULDBLOCK
          The  file  descriptor  fd refers to a socket and has been marked
          nonblocking   (O_NONBLOCK),   and   the   read   would    block.
          POSIX.1-2001  allows  either error to be returned for this case,
          and does not require these constants to have the same value,  so
          a portable application should check for both possibilities.
0 голосов
/ 22 ноября 2011

Я полагаю, вы не можете знать, будет ли когда-либо больше данных в канале. Итак, если вы контролируете процесс записи в канал, вам нужно написать согласованную специальную последовательность байтов «END-OF-DATA», чтобы читатель знал, когда остановиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...