From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32103 invoked by alias); 6 Jul 2010 21:30:25 -0000 Received: (qmail 32094 invoked by uid 22791); 6 Jul 2010 21:30:25 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD 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; Tue, 06 Jul 2010 21:30:19 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 635982BABFF; Tue, 6 Jul 2010 17:30:17 -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 vWdVWAoidV1m; Tue, 6 Jul 2010 17:30:17 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 296312BAB89; Tue, 6 Jul 2010 17:30:17 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id D4785F5895; Tue, 6 Jul 2010 14:30:01 -0700 (PDT) From: Joel Brobecker To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [RFA/gdbserver] Unexpected EOF read from socket after inferior exits. Date: Tue, 06 Jul 2010 21:30:00 -0000 Message-Id: <1278451801-10588-1-git-send-email-brobecker@adacore.com> 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: 2010-07/txt/msg00104.txt.bz2 This is on GNU/Linux. GDBserver does not exit properly when the inferior exits, as demonstrated with any program using the procedure below: % gdbserver-head :4444 simple_main Process simple_main created; pid = 25681 Listening on port 4444 Then, in another terminal, start GDB, connect to GDBserver, and run the program to completion: % gdb-head simple_main (gdb) tar rem :4444 (gdb) cont Continuing. Program exited normally. Going back to the terminal where GDBserver is running, we see the following output: Child exited with status 0 readchar: Got EOF Remote side has terminated connection. GDBserver will reopen the connection. Listening on port 4444 The problem is that we're missing a call to mourn_inferior. As a result, after we've handled the vCont packet, we fail to notice that there are no process left to debug (target_running() returns true), and thus try to continue reading from the remote socket. However, since GDB just disconnected after having received the "exit with status 0" reply to the vCont request, the read triggers the EOF exception. This patch fixes the problem by calling mourn_inferior after receiving an inferior-exited event when in all-stop mode. I know there are reasons why we don't call the mourning code right after the wait like we used to. It seems that, in that case, we can because we exit gdbserver shortly after. I really don't know whether this is the right approach or not - it feels fragile to me. For now, I took the lazy approach, but I noticed that the resume-and-if-nonstop-send-ok-else-wait-send-reply code in both handle_v_cont and myresume are identical and I think should be identical, so perhaps we should factorize this code as well. The problem is not all that serious in terms of the actual damage, but I do feel that it's sufficiently visible and annoying that we should have a fix for GDB 7.2. gdb/ChangeLog: * server.c (handle_v_cont): Call mourn_inferior if process just exited. (myresume): Likewise. Tested on x86_64-linux. --- gdb/gdbserver/server.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 226d123..9125f0e 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1779,6 +1779,10 @@ handle_v_cont (char *own_buf) last_ptid = mywait (minus_one_ptid, &last_status, 0, 1); prepare_resume_reply (own_buf, last_ptid, &last_status); disable_async_io (); + + if (last_status.kind == TARGET_WAITKIND_EXITED + || last_status.kind == TARGET_WAITKIND_SIGNALLED) + mourn_inferior (find_process_pid (ptid_get_pid (last_ptid))); } return; @@ -2079,6 +2083,10 @@ myresume (char *own_buf, int step, int sig) last_ptid = mywait (minus_one_ptid, &last_status, 0, 1); prepare_resume_reply (own_buf, last_ptid, &last_status); disable_async_io (); + + if (last_status.kind == TARGET_WAITKIND_EXITED + || last_status.kind == TARGET_WAITKIND_SIGNALLED) + mourn_inferior (find_process_pid (ptid_get_pid (last_ptid))); } } -- 1.7.1