Swiggity Swooty
Swiggity Swooty

Reputation: 217

C - How do you use select() with multiple pipes?

I'm having a difficult time figuring out how select() is suppose to work with pipes in UNIX. I've scanned the man pages several times, and I don't completely understand the given definition.

From reading the man pages, I was under the impression that select() would make the system wait until one of the file descriptors given could make a read (in my case) from a pipe without blocking.

Here's some of my outline code[EDITED]:

int size, size2;
fd_set rfds;
struct timeval tv;
char buffer[100];
char buffer2[100];
int retval;

while(1)
{
    FD_ZERO(&rfds);
    FD_SET(fd[0], &rfds);
    FD_SET(fd2[0], &rfds);
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    retval = select(2, &rfds, NULL, NULL, &tv); //2 seconds before timeout

    if(retval == -1)
       perror("Select failed.\n");
    else if(retval)
    {
       size = read(fd[0], buffer, sizeof(buffer));
       if(size > 0)
          printf("Parent received from even: %s\n", buffer);
       size2 = read(fd2[READ], buffer2, sizeof(buffer2));
       if(size2 > 0)
          printf("Parent received from odd: %s\n", buffer2);
    }
    else
       printf("No data written to pipe in 2 last seconds.\n");
}

I have two pipes here. Two children processes are writing to their respective pipes and the parent has to read them both in.

As a test, I write a small string to each pipe. I then attempt to read them in and prevent blocking with select. The only thing that gets printed out is the string from the even pipe. It appears to still be blocking. I am becoming frustrated as I feel like I'm missing something on the man pages. Could someone tell me what I'm doing wrong?

Upvotes: 2

Views: 4763

Answers (2)

Jander
Jander

Reputation: 5637

After select() returns, 0 or more of your file descriptors will be in a "ready" state where you can read them without blocking. But if you read one that's not ready, it will still block. Right now you are reading all of them, and since select() only waits until one is ready, it's very likely that another will not be.

What you need to do is figure out which ones are ready, and only read() from them. The return value of select() will tell you how many are ready, and you can ask if a specific one is ready with the ISSET() macro.

Upvotes: 5

Ed Heal
Ed Heal

Reputation: 60007

  1. You need to use FD_ZERO() - see select before the FD_SET
  2. Set the timeout values just before the select. Those values are changed through the select

Upvotes: 1

Related Questions