From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14994 invoked by alias); 12 Jan 2006 00:11:26 -0000 Received: (qmail 17468 invoked by uid 22791); 11 Jan 2006 21:47:40 -0000 X-Spam-Check-By: sourceware.org Received: from voldemort.codesourcery.com (HELO sethra.codesourcery.com) (65.74.133.5) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 11 Jan 2006 21:47:38 +0000 Received: from sethra.codesourcery.com (localhost.localdomain [127.0.0.1]) by sethra.codesourcery.com (8.12.11/8.12.11) with ESMTP id k0BLlaaS000701 for ; Wed, 11 Jan 2006 13:47:36 -0800 Received: (from mitchell@localhost) by sethra.codesourcery.com (8.12.11/8.12.11/Submit) id k0BLlatG000696; Wed, 11 Jan 2006 13:47:36 -0800 Date: Thu, 12 Jan 2006 00:11:00 -0000 Message-Id: <200601112147.k0BLlatG000696@sethra.codesourcery.com> From: Mark Mitchell To: gdb-patches@sources.redhat.com Subject: PATCH: Detect closed file descriptors on Windows Reply-to: mark@codesourcery.com Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-01/txt/msg00116.txt.bz2 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 * 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 ----