select() returns on unwanted fd's

select() returns on unwanted fd's

Post by Thomas Engstr » Wed, 21 Apr 1993 20:27:03



I am using select(2) in a program that forks another process and duplicates
its stdin & stderr. Something like this:

/* Pseudocode follows */
pipe();

fork();

if (child) {
   close_some_pipe_ends();
   dup_my_std(in, out, err);
   close_my_std(in, out, err);
   execl(...);

Quote:}

else if (parent) {
/* End of pseudocode, but this is actually part of a function */
  char
    ebuf[MAXBUFF],
    ibuf[MAXBUFF],
    ttyin[80];

  int
    n,
    rfd,  /* Read fd from child's stdout */
    wfd,  /* Write fd to child's stdin */
    efd,  /* Read fd from child's stderr */
    maxfdp1;

  fd_set
    ready,
    readfrom;

  struct timeval
    tmout;

  maxfdp1 = (rfd > wfd) ? ((rfd > efd) ? rfd : efd)
    : ((wfd > efd) ? wfd : efd);
  maxfdp1++;

  FD_ZERO(&readfrom);
  FD_SET(rfd, &readfrom);
  FD_SET(efd, &readfrom);

  tmout.tv_sec = 0;
  tmout.tv_usec = 0;

  fcntl(rfd,F_SETFL,O_NDELAY);  /* Don't wait on reads */
  fcntl(efd,F_SETFL,O_NDELAY);

  do {
    ready = readfrom;
    if ((n = select(maxfdp1, &ready, (fd_set *) 0, (fd_set *) 0, &tmout)) < 0)
      break;
    if (FD_ISSET(rfd, &ready)) {
      if ((n = read(rfd, ibuf, MAXBUFF)) > 0) {
        ibuf[n] = '\0';
        printf("%s", ibuf);
        fflush(stdout);
      }
      else
        return(-1);
    }
    if (FD_ISSET(efd, &ready)) {
      errno = 0;
      if ((n = read(efd, ebuf, MAXBUFF)) > 0) {
        ebuf[n] = '\0';
/* Here I plan to insert some analyzis on the error messages, but right now
   I just print them on the tty */
        fprintf(stderr, "%s", ebuf);
        fflush(stderr);
      }
      else
        return(-2);
    }
  } while (FD_ISSET(rfd, &readfrom) || FD_ISSET(efd, &readfrom));
  return(0);

Quote:}

...

From what I understand, select() should return ONLY when there is some data
to read on rfd or efd. But select() seems to return when any of the file-
descriptors 0..maxfpd1 is ready for reading or writing. In this range we
can find the parents stdin and stdout, and select() returns on these.

I want to keep parents stdin and stdout open, but not select() to take any
notice of them. What am I doing wrong? How should I do?

Many thanks to anyone who knows and answer me.

                /Thomas
--
_______________________________________________________________________________
                             |            Thomas Engstrom | +46 13 28 1260
               X             |    University of Linkoping | fax: +46 13 28 2800

 
 
 

select() returns on unwanted fd's

Post by Oliver Lauma » Thu, 22 Apr 1993 19:29:20


() [...]
() FD_ZERO(&readfrom);
() FD_SET(rfd, &readfrom);
() FD_SET(efd, &readfrom);
() tmout.tv_sec = 0;
() tmout.tv_usec = 0;
() [...]
() do {
()   ready = readfrom;
()   if ((n = select(maxfdp1, &ready, (fd_set *) 0, (fd_set *) 0, &tmout)) < 0)
()     break;
()   if (FD_ISSET(rfd, &ready)) {
()     [...]
()   }
()   if (FD_ISSET(efd, &ready)) {
()     [...]
()   }
() } while (FD_ISSET(rfd, &readfrom) || FD_ISSET(efd, &readfrom));

I can think of at least two reasons why the program fragment doesn't
behave like you expect.

First, specifying a timeout with both tv_sec and tv_usec equal to zero
causes the call to select() to return immediately, i.e. you are just
polling the file descriptors without waiting for them to become ready
(busy-waiting).  If you don't want a timeout, use (struct timeval *)0.

Second, you have to (re-)initialize the file descriptor masks prior to
each call to select(), not just once in the beginning.  The file
descriptor masks are input/output parameters, i.e. select() overwrites
the bits you set.

 
 
 

select() returns on unwanted fd's

Post by Georg S. Nikod » Sat, 24 Apr 1993 14:14:46


 Thomas> From what I understand, select() should return ONLY when
 Thomas> there is some data to read on rfd or efd. But select() seems
 Thomas> to return when any of the file- descriptors 0..maxfpd1 is
 Thomas> ready for reading or writing. In this range we can find the
 Thomas> parents stdin and stdout, and select() returns on these.

From what you understand, you're correct except that you didn't
read the part about the timeout value.  If you pass a null pointer
then select() will block forever until there is something on one
of the selected file descriptors.  If, however, you pass a pointer
to a struct timeval with zeroes in it, you are effecting a poll; which
means to say that select() will return immediately upon setting the
fd_set structures accordingly.
--
Georg S. Nikodym  -  (416) 272-5198 / 720-4729
Noweh Software - Mississauga, Ontario, CANADA
UUCP:   {comspec.com, lsuc.on.ca, uunet.ca}!noweh!georgn

 
 
 

1. Does select() return if the FD changed before select() was called?

Does a select() call return if the file descriptor it is watching changed
before the select() was called if the file descriptor hasn't been read or
written to since the change? For an illustration:

while ( select() ) {
    //Do some stuff here
    //One of the file descriptors select() watches happens to change right
here
    //Do some more stuff

Will select return on the next while() iteration because of the file
descriptor that changed in the middle of the loop? Or will it only watch for
descriptors that change since the select() call was made, which means my
program would block in select() without noticing the change that happened in
the last loop?

The man page doesn't seem to say much about this.

Also, if anyone can recommend any good books on programming TCP
clients/servers on POSIX and/or Win32 systems I'd appreciate it.

LKembel

2. Unix time function

3. RH 2.2.5 select() only returns 1 FD as ready even when more are

4. Help, problem with pppd terminating connections

5. How many FD's can select() handle?

6. cpu cooler

7. poll() doesn't return POLLIN from pipe() fd.

8. too much timer simplification...

9. open() doesn't return lowest avail fd on Solaris

10. Select returns data available read returns no data

11. When do read() return 0 despite that select() returned 1

12. select() doesn't return on socket descriptor

13. Does select return "read ready" or "won't block" status?