I use a pipe to read the output of a function by passing it a file descriptor. To read the output asynchronously I setup the “read” end of the pipe in ASYNC NON BLOCKING mode and I configure an IO handler using SIGACTION. My code looks like the following:
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);
The problem is that if I omit the sleep function call I can close the pipe and disable the SIGIO handler before the output is completed. The consequence is that the application abort due to an unhandled SIGIO signal (message “I/O possible”).
How can I make sure that all the output have been read from the pipe before disabling the SIGIO handler ?
To get the number of readable bytes, you might use the
ioctlFIONREAD, which is not very portable. See this question as a contrived example.You can also test availability of things to read with poll, select and friends.
And the end-of-file condition is reported with
readreturning 0 as count.ADDENDA
according to read(2) syscall man page,
readfails with errno ==: