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

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

Post by Felix Morley Fin » Mon, 15 Feb 1999 04:00:00



I have a little test program here which opens two named pipes and
selects on them for read ready.  If the pipes are opened read-write,
the select status means "read ready".  If the pipes are opened
read-only, the status means "read ready" only until the first byte has
been read; from then on, the status means "won't block", and results
in no wait at all, and zillions of empty reads.

All the documentation I can find either states or implies that the
status should only be "read ready".  Why does a read-only open change
this?  What am I misunderstanding?

As a side question, this test program opens non-blocking because
opening a named pipe read-only does not return until there is a
writer.  What is the reasoning behind this?  If this is why select
returns "won't block" status, then why does it return "read ready"
status before the first byte has been read?

It's the difference in behavior before and after the first byte has
been read that puzzles me.  I can understand either status, I'd just
be happier if it were consistent.

This is Linux kernel 2.0.33 / glibc 2.1 (mongrel 4 year old
Slackware), and 2.0.35 (Red Hat 5.1) (both stock 2.0.7 and 2.1).

--------------------------------
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>

/* Select anomaly.  Select on a named pipe opened read-only returns
   "read ready" status until the first byte has been read.  Afterwards
   it returns "won't block" status.  Select always returns "read
   ready" status if opened for read-write.  This opens two pipes and
   shows the behavior as bytes are read.  It terminates when a \n is
   read on either pipe. */

char            *(pipename [2]) = { "/tmp/tstpipe1", "/tmp/tstpipe2" };
int             pipefd [2] = { -1, -1 };
fd_set          pipefds;
int             fdmax = 0;
int             emptyReads [2] = { 0, 0 };
int             lastEmpty = -1;

void
errexit (int pnum)
{
  perror (pipename [pnum]);
  exit (1);

Quote:}

void
openPipe (int ro) {
  int   pnum;
  int   flg = (ro ? O_RDONLY : O_RDWR) | O_NONBLOCK;

  FD_ZERO (&pipefds);
  for (pnum = 0; pnum < 2; pnum++) {
    if ((mkfifo (pipename [pnum], 0622) < 0) ||
        (pipefd [pnum] = open (pipename [pnum], flg)) < 0)
      errexit (pnum);

    FD_SET (pipefd [pnum], &pipefds);
    if (pipefd [pnum] + 1 > fdmax)
      fdmax = pipefd [pnum] + 1;
  }

Quote:}

void
closePipe (void)
{
  int   pnum;

  for (pnum = 0; pnum < 2; pnum++) {
    if ((close (pipefd [pnum]) < 0) || (unlink (pipename [pnum]) < 0))
      errexit (pnum);

    FD_CLR (pipefd [pnum], &pipefds);
    pipefd [pnum] = -1;
  }

Quote:}

int
readPipe (int pnum)
{
  char          c;
  int           i;

  if ((i = read (pipefd [pnum], &c, 1)) == 1) {
    if (c == '\n')
      return (1);                       /* Watch for eol */

    if (emptyReads [0] || emptyReads [1]) {
      emptyReads [0] = emptyReads [1] = 0;
      printf ("\n");  /* Preserve the count display */
    }
    printf ("%s: %c\n", pipename [pnum], c);
    return (0);
  }

  if ((i < 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
      errexit (pnum);

  emptyReads [pnum]++;
  printf ("Empty = %d %d\r", emptyReads [0], emptyReads [1]);
  return (0);

Quote:}

void
sleepy (void)
{
  while (1) {
    fd_set      fds;
    int         i;

    fds = pipefds;
    if ((i = select (fdmax, &fds, NULL, NULL, NULL)) <= 0) {
      perror ("Select");
      exit (1);
    }

    for (i = 0; i < 2; i++)
      if (FD_ISSET (pipefd [i], &fds) && readPipe (i))
        return;         /* EOL received */
  }

Quote:}

int
main (int argc, char *argv[])
{
  int   ro = -1;

  if (argc == 2) {
    if (argv [1] [0] == 'r')
      ro = 1;
    else if (argv [1] [0] == 'w')
      ro = 0;
  }
  if (ro < 0) {
    fprintf (stderr, "Usage:\n%s [r | w]\n  o = open read-only\n  n = open read-write\n", argv [0]);
    exit (1);
  }
  openPipe (ro);
  printf ("Open for %s\n", ro ? "read-only" : "read-write");
  printf ("Echo -n to %s or %s to terminate\n", pipename [0], pipename [1]);
  printf ("Echo a new line to terminate\n");
  sleepy ();
  closePipe ();
  if (emptyReads [0] || emptyReads [1])
    printf ("\n");    /* Preserve the last count */
  exit (0);

Quote:}

--------------------------------

--
            ... _._. ._ ._. . _._. ._. ___ .__ ._. . .__. ._ .. ._.

  PGP = 91 B3 94 7C E9 E8 76 2D   E1 63 51 AA A0 48 89 2F  ITAR license #4933
I've found a solution to Fermat's Last Theorem but I see I've run out of room o

 
 
 

1. """"""""My SoundBlast 16 pnp isn't up yet""""""""""""

My machine: P166+mmx, 32mb ram, 4gb HD with Win95 and Win NT 4.0 and
redhat5.1 co-existed in different partitions.

I issued "sndconfig" within a xterm inside X Window, The program
detects the SB 16 pnp card sets it up with no error message, but when
it launch ModProbe to test out, it gets a message states: An error was
encountered running the ModProbe program."  I tried different IRQ
settings, all ends with the same message.

2nd, When I try to mount /dev/cdrom from File Systerm Manager, the
following error is returned:  Can't find /dev/hdb in /etc/mtab or
/etc/fstab.

3nd, When my machine boots, it halts at "Sendmail" for about 3-5 mins
before it goes to next step.  Obviously there isn't any mail system on
the machine right now because it is a standalone.  How can take this
mail thing out and speed up booting?

last one, Is my Zoom 56k PCI FaxModem a Windmodem that Linux can't use
to connect me to my local isp?

Experts help me out please. thanks.

2. TNT Card support for KDE

3. GETSERVBYNAME()????????????????????"""""""""""""

4. Comtrol Rocketport

5. Heritage of "gettimeofday", "gethostname", "select"?

6. VCDImager: custom XML files

7. Type "(", ")" and "{", "}" in X...

8. Q: Can I change strings in files with binary data.

9. Cygwin bash "id -un" returns "Administrator" when I'm not

10. Second drive (/dev/fd1) won't "DO IT" and "DO IT"

11. "syslogd: unknown priority "24" " error - won't boot!

12. Second drive (dev/fd1) won't "DO IT" and "DO IT"

13. Any "ready-to-run" projects for "servers" available?