bug-gdb
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gdb-5.0 and select()


From: Graeme Peterson
Subject: gdb-5.0 and select()
Date: Fri, 29 Sep 2000 14:26:50 -0400 (EDT)

Hi.  I have found what I think is a bug in gdb/ser-unix.c in
gdb-5.0.  The functions wait_for() and ser_unix_wait_for() do
FD_ZERO() and FD_SET() before a loop on select() that either 
returns or continues based on the return value of select.  If 
select returns -1 with EINTR, we continue and loop on select again.

The behavior of select() in the EINTR case seems to be platform 
dependant, specifically regarding the contents of the descriptor
sets after the EINTR.

man select:
On sparc-sun-solaris2.6:

        On failure, the objects pointed to by the  readfs,  writefs,
        and  errorfds  arguments  are  not modified.


On linux Redhat5.2:

        On error, -1 is returned, and errno is set appropriately; the
        sets and timeout become undefined, so do not rely on their
        contents after an error.


On our new OS (QNX RTP/Neutrino):

        On return, the select() function replaces the given descriptor 
        sets with subsets consisting of those descriptors that are ready 
        for the requested operation. 


Three different behaviors.  In my case, I placed the FD_ZERO() and
FD_SET() calls inside the while loop above the select(), and this 
fixed it for me.  Should this be the default?  I do not see how it
would break things for other platforms.

ie:  (for ser_unix_wait_for and similarly for wait_for)

int
ser_unix_wait_for (serial_t scb, int timeout)
{
  int numfds;
  struct timeval tv;
  fd_set readfds, exceptfds;

  FD_ZERO (&readfds);
  FD_ZERO (&exceptfds);

  tv.tv_sec = timeout;
  tv.tv_usec = 0;

  FD_SET (scb->fd, &readfds);
  FD_SET (scb->fd, &exceptfds);

  while (1)
    {
      if (timeout >= 0)
        numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
      else
        numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);

      if (numfds <= 0)
        {
          if (numfds == 0)
            return SERIAL_TIMEOUT;
          else if (errno == EINTR)
            continue;
          else
            return SERIAL_ERROR;        /* Got an error from select or poll */
        }

      return 0;
    }
}

becomes

int
ser_unix_wait_for (serial_t scb, int timeout)
{
  int numfds;
  struct timeval tv;
  fd_set readfds, exceptfds;

  tv.tv_sec = timeout;
  tv.tv_usec = 0;

  while (1)
    {
      FD_ZERO (&readfds);
      FD_ZERO (&exceptfds);

      FD_SET (scb->fd, &readfds);
      FD_SET (scb->fd, &exceptfds);

      if (timeout >= 0)
        numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
      else
        numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);

      if (numfds <= 0)
        {
          if (numfds == 0)
            return SERIAL_TIMEOUT;
          else if (errno == EINTR)
            continue;
          else
            return SERIAL_ERROR;        /* Got an error from select or poll */
        }

      return 0;
    }
}

Thanks.
GP

---------------
Graeme Peterson
QNX Tools Group
address@hidden




reply via email to

[Prev in Thread] Current Thread [Next in Thread]