From patchwork Mon Jun 25 13:09:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 28011 Received: (qmail 6772 invoked by alias); 25 Jun 2018 13:09:40 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 6615 invoked by uid 89); 25 Jun 2018 13:09:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Hx-spam-relays-external:209.85.128.195, H*RU:209.85.128.195, connecting X-HELO: mail-wr0-f195.google.com Received: from mail-wr0-f195.google.com (HELO mail-wr0-f195.google.com) (209.85.128.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 25 Jun 2018 13:09:37 +0000 Received: by mail-wr0-f195.google.com with SMTP id g18-v6so13617450wro.7 for ; Mon, 25 Jun 2018 06:09:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=Pj0MwHonsZZueQ2scon6nX1invSUeNQhGUaj2fzb9s4=; b=DFqdOGXZ4DvNSvU60kil/ElRrRc+7UOPlzAO//2VVbGmAktZP8+EFLGLdHB3HgSewj oNvGaa+4PFnd2LdAqztMZ5oQ3eXwjRsHskCElfYPKdOCOmqaspo6eNMBylBbj0Xek5U2 639MGBFTEcImwecEd6RDwrljtj92PTXM8F9z8t4ybuek7EeoxCwBRzi/11c6YGZmkqgP MXfo/FljUgdJFdGanUEUSyNUUAFrtWNzLol7jn8d85jR4xVyF3b95elTwDjieJCknoad sIcbiHAYj9orrBg47Jc1Yj6ge4mJb2KPU/YFMzsiSY3BQI0WMdvrw/gKa1SU9yoXd+O5 60gQ== X-Gm-Message-State: APt69E3etSaSEoLkvq0+v2PnkMQylFYVbOZRf8jZBeZMVh3ERsnIfZa7 vOvuVx+y22Hf4SaktozdOlLRpf/z X-Google-Smtp-Source: AAOMgpcIC5ltLS39hE6wdAK/3E243FH0Zl3eMtdcmlN8rCQXQLdtd23teTpU6JsDDt6spj2RPaZFlg== X-Received: by 2002:adf:9582:: with SMTP id p2-v6mr9872420wrp.252.1529932175288; Mon, 25 Jun 2018 06:09:35 -0700 (PDT) Received: from localhost (host81-140-212-80.range81-140.btcentralplus.com. [81.140.212.80]) by smtp.gmail.com with ESMTPSA id j10-v6sm29166213wrr.47.2018.06.25.06.09.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 Jun 2018 06:09:34 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH 2/2] gdb: Clean up inferior list when reconnecting to new target Date: Mon, 25 Jun 2018 14:09:30 +0100 Message-Id: <39cccae98fed5a88b2fd5b40167aedb55be91578.1529931757.git.andrew.burgess@embecosm.com> In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes When connected to a target and running an inferior, if the inferior forks then a new, inferior is created to track the child process. Usually the second inferior (the child process) will be automatically cleaned up (removed) by GDB once the child has completed. However, if we connect to a new target then the second inferior is left around, and we can even end up using the second inferior in order to run a program on the new target, for example in this session: (gdb) target extended-remote :2347 (gdb) file /path/to/exe (gdb) set remote exec-file /path/to/exe (gdb) set detach-on-fork off (gdb) break breakpt (gdb) run # ... hits breakpoint (gdb) info inferiors Num Description Executable * 1 process 15406 /path/to/exe 2 process 15407 /path/to/exe (gdb) kill Kill the program being debugged? (y or n) y (gdb) info inferiors Num Description Executable * 1 /path/to/exe 2 process 15433 /path/to/exe (gdb) target extended-remote :2348 (gdb) file /path/to/exe (gdb) set remote exec-file /path/to/exe (gdb) run # ... hits breakpoint (gdb) info inferiors Num Description Executable 1 /path/to/exe * 2 process 15408 /path/to/exe 3 process 15409 /path/to/exe (gdb) Notice how after connecting to the second extended-remote target, and then running the test program we now have inferiors 1, 2, and 3. There's nothing really _wrong_ with this, but a better experience would, I think, be to have only inferiors 1 and 2 in the new target's session. The issue here is that in target.c:dispose_inferior GDB uses switch_to_thread, which also switches the current inferior. This leaves the last inferior in the list selected after target.c:target_preopen has completed. We could change target.c:dispose_inferior to ensure the selected inferior is not left changed, however, in the above example, I think that, even if the user manually selected inferior 2 _before_ connecting to the new target, the best behaviour would still be for GDB to switch back to inferior 1. This seems to suggest that the right thing to do is have GDB _choose_ a new inferior as part of target_preopen, after which is can call prune_inferiors to remove transient inferiors from the list. An existing test is extended to cover this behaviour. gdb/ChangeLog: * target.c (find_first_killed_inferior): New function. (target_preopen): Use find_first_killed_inferior to reset selected inferior, and prune killed inferior as appropriate. gdb/testsuite/ChangeLog: * gdb.base/extended-remote-restart.exp: Extend. --- gdb/ChangeLog | 6 ++++ gdb/target.c | 35 ++++++++++++++++++++++ gdb/testsuite/ChangeLog | 4 +++ gdb/testsuite/gdb.base/extended-remote-restart.exp | 6 ++++ 4 files changed, 51 insertions(+) diff --git a/gdb/target.c b/gdb/target.c index 7c297495703..870b2357688 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2046,6 +2046,31 @@ dispose_inferior (struct inferior *inf, void *args) return 0; } +/* Callback for iterate_over_inferiors. Record in ARG the first killed + inferior. If we find an inferior that is both killed and not removable, + this is returned in preference. The definition of "first" here is + pretty loose, and depends on the order in the inferior list. */ + +static int +find_first_killed_inferior (struct inferior *inf, void *arg) +{ + struct inferior **infp = (struct inferior **) arg; + + if (inf->pid == 0) + { + if (!inf->removable) + { + *infp = inf; + return 1; + } + else if (*infp == nullptr) + *infp = inf; + } + + return 0; +} + + /* This is to be called by the open routine before it does anything. */ @@ -2062,6 +2087,16 @@ target_preopen (int from_tty) iterate_over_inferiors (dispose_inferior, NULL); else error (_("Program not killed.")); + + /* The call to DISPOSE_INFERIOR will leave the last inferior we + killed selected. Reset the selection to the earliest inferior + that is killed and not removable. The prune any other killed + inferiors. */ + struct inferior *inf = nullptr; + iterate_over_inferiors (find_first_killed_inferior, &inf); + if (inf != nullptr) + set_current_inferior (inf); + prune_inferiors (); } /* Calling target_kill may remove the target from the stack. But if diff --git a/gdb/testsuite/gdb.base/extended-remote-restart.exp b/gdb/testsuite/gdb.base/extended-remote-restart.exp index 39fcb9e2e58..fb4bdd1755c 100644 --- a/gdb/testsuite/gdb.base/extended-remote-restart.exp +++ b/gdb/testsuite/gdb.base/extended-remote-restart.exp @@ -119,6 +119,12 @@ proc test_reload { do_kill_p follow_child_p } { } else { fail "reconnect after fork" } + + gdb_test "info inferiors" \ + [multi_line \ + " Num Description Executable.*" \ + "\\* 1 +${dead_inf_ptn} \[^\r\n\]+" ] \ + "Check inferiors after reconnect" } # Run all combinations of the test.