Reputation: 127
I've been writing a small program in C++ for linux using inter process communication. I had a problem when trying to read in a non-blocking way with one process and write (blocking) with another process. The issue looks like this, when the parent tries to read the pipe with O_NONBLOCK
(or O_NDELAY
) it never reads a single byte and when the child tries to write on the pipe, it fails and the SIGPIPE
broken pipe signal is sent. Here is an example of the code:
// Parent process
mkfifo(PROC_COPROC, 0666);
int fd_co = open(PROC_COPROC, O_RDONLY | O_NDELAY);
char c;
int n;
fcntl(fd_co,F_SETFL,0); //fix it
while ((n = read(fd_co, &c, 1)) > 0)
{
printf("%c", c);
}
close(fd_co);
// Child process
int fd = open(PROC_COPROC, O_WRONLY | O_APPEND);
if ( fd != -1 )
{
write( fd , "message\n" , 8); //Fails here if flag not set
}
else
printf("Ne peut pas ecrire sur le fifo\n");
close(fd);
I finally found a way to resolve this by using fcntl(fd_co,F_SETFL,0);
right after the non-blocking open call.
After reading the man page, I couldn't find any (simple) explanation why I sould reset the file descriptor's flag if I want to read non-blocking and write blocking.
Anyone has an explanation or am I doing it wrong?
Upvotes: 0
Views: 7423
Reputation: 74018
The "problem" with O_NDELAY is, that read returns -1
and sets errno to EAGAIN
, when there's no data available. So, you must test the return value of read
for -1
and errno and then read again.
Your "fix" just resets O_NDELAY, which makes read block again, if there's nothing to read from the FIFO.
See also read
RETURN VALUE
... On error, -1 is returned, and errno is set appropriately.ERRORS
EAGAIN The file descriptor fd refers to a file other than a socket and has been marked nonblocking (O_NONBLOCK), and the read would block.
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.
You might also consider using select
, or poll
as @BasileStarynkevitch suggested, if blocking is a problem in your case.
Upvotes: 4