This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Detect closed file descriptors on Windows


At present, the gdb_select function (which provides the select
interface on non-Cygwin Windows) never marks a file descriptor as
having experienced an exception; in other words, the third argument to
gdb_select is always the empty set upon return.

The Newlib exit() implementation closes file descriptor zero.  When
GDB is using its built-in simulator, the semi-hosting support maps the
target's file descriptor zero to the host file descriptor zero.  So,
when the target program exits, GDB's standard input goes away.  On
UNIX, GDB notices that because select marks file descriptor zero as
having experienced an exception, and thus, GDB itself exits.  

On Windows, because gdb_select doesn't mark the file descriptor as
having experienced an exception, GDB just runs around calling
gdb_select repeatedly, eating CPU.  (It might be better for GDB to
duplicate descriptor zero, so that GDB's own standard input doesn't go
away, but that's another issue.)  

This patch makes the Windows behavior match the UNIX behavior, by
noticing when get_osfhandle returns INVALID_HANDLE_VALUE.

OK to apply?

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2006-01-08  Mark Mitchell  <mark@codesourcery.com>

	* gdb/event-loop.c (gdb_select): Detect file descriptors that have
	been closed.

Index: event-loop.c
===================================================================
RCS file: /cvs/src/src/gdb/event-loop.c,v
retrieving revision 1.26
diff -c -5 -p -r1.26 event-loop.c
*** event-loop.c	25 Apr 2005 23:51:33 -0000	1.26
--- event-loop.c	9 Jan 2006 03:20:55 -0000
*************** gdb_select (int n, fd_set *readfds, fd_s
*** 747,772 ****
    DWORD event;
    DWORD num_handles;
    int fd;
    int num_ready;
  
    num_handles = 0;
    for (fd = 0; fd < n; ++fd)
      {
-       /* EXCEPTFDS is silently ignored.  GDB always sets GDB_EXCEPTION
- 	 when calling add_file_handler, but there is no natural analog
- 	 under Windows.  */
        /* There is no support yet for WRITEFDS.  At present, this isn't
  	 used by GDB -- but we do not want to silently ignore WRITEFDS
  	 if something starts using it.  */
        gdb_assert (!FD_ISSET (fd, writefds));
!       if (FD_ISSET (fd, readfds))
  	{
! 	  gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
! 	  handles[num_handles++] = (HANDLE) _get_osfhandle (fd);
! 	}
!     }
    event = WaitForMultipleObjects (num_handles,
  				  handles,
  				  FALSE,
  				  timeout 
  				  ? (timeout->tv_sec * 1000 + timeout->tv_usec)
--- 747,789 ----
    DWORD event;
    DWORD num_handles;
    int fd;
    int num_ready;
  
+   num_ready = 0;
    num_handles = 0;
    for (fd = 0; fd < n; ++fd)
      {
        /* There is no support yet for WRITEFDS.  At present, this isn't
  	 used by GDB -- but we do not want to silently ignore WRITEFDS
  	 if something starts using it.  */
        gdb_assert (!FD_ISSET (fd, writefds));
!       if (FD_ISSET (fd, readfds) 
! 	  && !FD_ISSET (fd, exceptfds))
! 	continue;
!       h = (HANDLE) _get_osfhandle (fd);
!       if (h == INVALID_HANDLE_VALUE)
  	{
! 	  /* If the underlying handle is INVALID_HANDLE_VALUE, then
! 	     this descriptor is no more.  */
! 	  if (FD_ISSET (fd, exceptfds))
! 	    ++num_ready;
! 	  continue;
! 	}
!       /* The only exceptional condition we recognize is a closed file
! 	 descriptor.  Since we have already checked for that
! 	 condition, clear the exceptional bit for this descriptor.  */
!       FD_CLR (fd, exceptfds);
!       if (FD_ISSET (fd, readfds))
!       {
! 	gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
! 	handles[num_handles++] = h;
!       }
!     }
!   /* If we don't need to wait for any handles, we are done.  */
!   if (!num_handles)
!     return num_ready;
    event = WaitForMultipleObjects (num_handles,
  				  handles,
  				  FALSE,
  				  timeout 
  				  ? (timeout->tv_sec * 1000 + timeout->tv_usec)
*************** gdb_select (int n, fd_set *readfds, fd_s
*** 777,790 ****
    gdb_assert (!(WAIT_ABANDONED_0 <= event
  		&& event < WAIT_ABANDONED_0 + num_handles));
    if (event == WAIT_FAILED)
      return -1;
    if (event == WAIT_TIMEOUT)
!     return 0;
    /* Run through the READFDS, clearing bits corresponding to descriptors
       for which input is unavailable.  */
!   num_ready = num_handles; 
    h = handles[event - WAIT_OBJECT_0];
    for (fd = 0; fd < n; ++fd)
      {
        HANDLE fd_h;
        if (!FD_ISSET (fd, readfds))
--- 794,807 ----
    gdb_assert (!(WAIT_ABANDONED_0 <= event
  		&& event < WAIT_ABANDONED_0 + num_handles));
    if (event == WAIT_FAILED)
      return -1;
    if (event == WAIT_TIMEOUT)
!     return num_ready;
    /* Run through the READFDS, clearing bits corresponding to descriptors
       for which input is unavailable.  */
!   num_ready += num_handles; 
    h = handles[event - WAIT_OBJECT_0];
    for (fd = 0; fd < n; ++fd)
      {
        HANDLE fd_h;
        if (!FD_ISSET (fd, readfds))
*************** gdb_select (int n, fd_set *readfds, fd_s
*** 796,809 ****
  	{
  	  FD_CLR (fd, readfds);
  	  --num_ready;
  	}
      }
-   /* We never report any descriptors available for writing or with
-      exceptional conditions.  */ 
-   FD_ZERO (writefds);
-   FD_ZERO (exceptfds);
  
    return num_ready;
  #else
    return select (n, readfds, writefds, exceptfds, timeout);
  #endif
--- 813,822 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]