From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26418 invoked by alias); 23 Apr 2009 19:14:58 -0000 Received: (qmail 26355 invoked by uid 22791); 23 Apr 2009 19:14:55 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_33 X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 23 Apr 2009 19:14:50 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 10BD92BACA2 for ; Thu, 23 Apr 2009 15:14:49 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id JQunehsbpPax for ; Thu, 23 Apr 2009 15:14:49 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id CAFFF2BAB95 for ; Thu, 23 Apr 2009 15:14:48 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id 2F14FF5924; Thu, 23 Apr 2009 12:14:46 -0700 (PDT) Date: Thu, 23 Apr 2009 19:14:00 -0000 From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA/commit] Handle EOF on terminals opened with ENONBLOCK... Message-ID: <20090423191446.GB7512@adacore.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="opJtzjQTFsWo+cga" Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-04/txt/msg00661.txt.bz2 --opJtzjQTFsWo+cga Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1850 This is an interesting situation that we encountered on AIX. At one point, I thought it might have been the same issue as the one that prevents us from running the testsuite on AIX, but no such luck, unfortunately. What happens is that we start GDB in a pseudo-terminal that has the O_NONBLOCK flag set. This is necessary because not doing so on AIX results in the child process never really dying, for some reason. The resulting processes appears as unkillable zombies: - 483384 - Only a reboot allowed us to get rid of them. We tried very hard to find out why they never died, but we couldn't figure it out. As far as we can tell, we do everything the way we're supposed to. Anyway, the attached patch enhances GDB to handle pseudo terminals configured that way. Before this patch, you'd see something like this happening: (gdb) start The program being debugged has been started already. Start it from the beginning ? (y or n) y !!!-> EOF [assumed Y] Breakpoint 2 at 0x100154f0: file foo.adb, line 4. Starting program: /dresden.a/brobecke/ex/foo foo () at foo.adb:4 4 end Foo; What happens is that, by the time GDB makes a read on the pseudo- terminal, there is nothing to read yet, and thus gets EOF back. The thing to do, to detect our case, is to check the errno value, and try again a little later if it's EAGAIN. 2009-04-23 Joel Brobecker * utils.c: Add include of gdb_usleep.h. (defaulted_query): Detect false EOF conditions that happen on terminals opened with the O_NONBLOCK flag when there is nothing to read. We've tested this patch on all the hosts that AdaCore supports. This includes GNU/Linux, Solaris, AIX, Tru64, MinGW... Would it be OK to commit? -- Joel --opJtzjQTFsWo+cga Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="EOF.diff" Content-length: 1077 diff --git a/gdb/utils.c b/gdb/utils.c index 57f267a..175b2fc 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -67,6 +67,8 @@ #include #include +#include "gdb_usleep.h" + #if !HAVE_DECL_MALLOC extern PTR malloc (); /* OK: PTR */ #endif @@ -1477,6 +1479,20 @@ defaulted_query (const char *ctlstr, const char defchar, va_list args) gdb_flush (gdb_stdout); answer = fgetc (stdin); + + /* On terminals opened with the NONBLOCK flag, fgetc can return EOF + when there is nothing to read. To distinguish this case from + a true EOF, we need to check the file error condition and see + if fgetc might have set errno to EAGAIN. */ + while (answer == EOF && ferror (stdin) && errno == EAGAIN) + { + /* Not a real EOF. Wait a little while and try again until + we read something. */ + clearerr (stdin); + gdb_usleep (10000); + answer = fgetc (stdin); + } + clearerr (stdin); /* in case of C-d */ if (answer == EOF) /* C-d */ { --opJtzjQTFsWo+cga--