Reputation: 20300
I have two pipes that both get different data at random points. What I want is to print the content from both pipes to stdout.
__________________
pipe1 | |
]==============> -----------.
| | \
| process1 | -----> stdout
pipe2 | | /
]==============> -----------´
|__________________|
My code looks about this in process1:
while (1) {
read(pipe1[0], &buff, sizeof(char));
write(1, &buff, sizeof(char));
read(pipe2[0], &buff2, sizeof(char));
write(1, &buff2, sizeof(char));
}
However that doesn't work as one read()
can be blocked(if no data is coming) while data comes from the other pipe.
How can I print simultaneously from both pipes without being blocked in one pipe? Or any other suggestion on how to solve this is welcome.
Upvotes: 1
Views: 591
Reputation: 77400
Use select
to wait on both sockets. When data is ready, it will tell you which pipes have data available.
void setnonblocking(int fd) {
int opts;
opts = fcntl(fd,F_GETFL);
if (opts < 0) {
perror("Couldn't get file descriptor flags");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(fd,F_SETFL,opts) < 0) {
perror("Couldn't set file descriptor to non-blocking");
exit(EXIT_FAILURE);
}
return;
}
#ifndef BUFSIZE
# define BUFSIZE 1024
#endif
void cat(fd_set* waiting, int fd) {
static char buf[BUFSIZE];
int readCnt;
if (FD_ISSET(fd, waiting)) {
while ((readCnt = read(fd, buf, BUFSIZE)) > 0) {
write(stdout, buf, readCnt);
}
if (readCnt < 0) {
perror("Error reading from pipe");
}
}
}
...
{
fd_set pipes, readable;
setnonblocking(pipes1[0]);
setnonblocking(pipes2[0]);
FD_ZERO(&pipes);
FD_SET(pipe1[0],&pipes);
FD_SET(pipe2[0],&pipes);
int ready;
while (1) {
if ((ready = select(2, &pipes, NULL, NULL, NULL)) > 0) {
cat(&pipes, pipe1[0]);
cat(&pipes, pipe2[0]);
} else {
// no time limit, so there was an error
perror("Error waiting for input");
exit(EXIT_FAILURE);
}
FD_SET(pipe1[0],&pipes);
FD_SET(pipe2[0],&pipes);
}
}
Note the above runs forever unless there's an error. You will likely want your program to stop at some point.
Upvotes: 3
Reputation: 1
You need to multiplex the inputs. The relevant system call is poll or select (or ppoll
or pselect
). The select tutorial is useful to read.
Upvotes: 2