Reputation: 2563
I have to write a program which monitors two named pipes and prints the information sent through either.
When the write end of one of the pipes is closed, the program will detect this and close and open the pipe again.
This is what I have written so far:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define BUF_SIZE 200
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
ssize_t n_read;
char buf[BUF_SIZE];
/* Open pipes */
int tuberia1_fd = open("tuberia1",O_RDONLY);
int tuberia2_fd = open("tuberia2",O_RDONLY);
while(1){
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait for an indefinite amount of time. */
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(2, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
exit(EXIT_FAILURE);
if(FD_ISSET(tuberia1_fd, &rfds)){
n_read = read(tuberia1_fd, &buf, BUF_SIZE);
if (n_read == 0){
close(tuberia1_fd);
tuberia1_fd = open("tuberia1", O_RDONLY);
}else{
buf[n_read] = '\0';
printf("tuberia1: %s", buf);
}
} else if (FD_ISSET(tuberia2_fd, &rfds)){
n_read = read(tuberia2_fd, &buf, BUF_SIZE);
if (n_read == 0){
close(tuberia2_fd);
tuberia2_fd = open("tuberia2", O_RDONLY);
}else{
buf[n_read] = '\0';
printf("tuberia2: %s", buf);
}
}
}
}
When I run it, the program locks, which is the expected behavior. But when I echo hello_world > tuberia1
there is no response from the program.
What is going on?
EDIT: As observed by GM below, I was incorrectly passing arguments to select
. After fixing that my program looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define BUF_SIZE 200
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
ssize_t n_read;
char buf[BUF_SIZE];
/* Open pipes */
printf("Opening tuberia1");
int tuberia1_fd = open("tuberia1",O_RDONLY);
printf("Opening tuberia2");
int tuberia2_fd = open("tuberia2",O_RDONLY);
while(1){
printf("Enter the loop");
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(tuberia1_fd, &rfds);
FD_SET(tuberia2_fd, &rfds);
/* Wait for an indefinite amount of time. */
tv.tv_sec = 5;
tv.tv_usec = 0;
int fd_max = (tuberia1_fd > tuberia2_fd) ? tuberia1_fd : tuberia2_fd;
retval = select(fd_max, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
exit(EXIT_FAILURE);
if(FD_ISSET(tuberia1_fd, &rfds)){
n_read = read(tuberia1_fd, &buf, BUF_SIZE);
if (n_read == 0){
close(tuberia1_fd);
tuberia1_fd = open("tuberia1", O_RDONLY);
}else{
buf[n_read] = '\0';
printf("tuberia1: %s", buf);
}
} else if (FD_ISSET(tuberia2_fd, &rfds)){
n_read = read(tuberia2_fd, &buf, BUF_SIZE);
if (n_read == 0){
close(tuberia2_fd);
tuberia2_fd = open("tuberia2", O_RDONLY);
}else{
buf[n_read] = '\0';
printf("tuberia2: %s", buf);
}
}
}
}
It still does not work. Running it under GDB shows that the program never progresses past the first open
.
Upvotes: 0
Views: 52
Reputation: 12898
You need to use FD_SET
on the file descriptors you're actually interested in -- namely tuberia1_fd
and tuberia2_fd
.
So something like...
while (1) {
FD_ZERO(&rfds);
FD_SET(tuberia1_fd, &rfds);
FD_SET(tuberia2_fd, &rfds);
int max;
if (tuberia1_fd > tuberia2_fd) {
max = tuberia1_fd;
} else {
max = tuberia2_fd;
}
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(max + 1, &rfds, NULL, NULL, &tv);
Upvotes: 1