From patchwork Fri Nov 18 16:42:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60841 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BEB1C384F483 for ; Fri, 18 Nov 2022 16:44:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BEB1C384F483 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789844; bh=uXsGKR1gf7ka4OweDqwOxB35/McxZZL5xLas572AGQw=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=D1NLymk86BPNoHtzHZGgbiyvrd8/fhQ0d8cO9hPHRQOz9nk3jalfF87lNlBYSw1jP vcves7iSzdsq7e/yL/IThagfhMwuoA8D5ddwAPhcr4LO8xnXgc2nPhcillKLkbDrKA +2XGl1d0HTBPd6Qr4HfHpe4RZQ7sg40yJGnIl2iw= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 29EC13852200 for ; Fri, 18 Nov 2022 16:43:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 29EC13852200 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-314-oe38ygGJOvezJOx6cJjaZQ-1; Fri, 18 Nov 2022 11:43:04 -0500 X-MC-Unique: oe38ygGJOvezJOx6cJjaZQ-1 Received: by mail-wm1-f71.google.com with SMTP id j2-20020a05600c1c0200b003cf7397fc9bso2493596wms.5 for ; Fri, 18 Nov 2022 08:43:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uXsGKR1gf7ka4OweDqwOxB35/McxZZL5xLas572AGQw=; b=srnAO4tMGVVwxDM85+sMaMk1mWzBNH3/eALNZlO+4HrNEda9UEuoqoH53KtsNDbQ1u l5/zDB0LBnB6em8ssAwEAFeCV70NPt4PUi7/2GW8hdurJyShOUKQxcxPrYjx9NXckU2/ xE0VfeG9EeHrBBZA7C+R6pya/KVUqerAf3XcCX/+6MDnr+Ssqn7YDg+dyXYOWO4286TU bPsyzh4Oy7KV/q2aJFRbSBkujAvUASUZu8wlYFVAiuIXvrYlB9BTEL7jdCs1XKouDGwO 3fmg8VE7HvkTnVqVrRs3Hb2cyTD5HyT+x12fVRMF9zJM14bhxAeYr5X23wKt8boBpufb 6aFQ== X-Gm-Message-State: ANoB5pnoeaeZD0/pFs9uOVgMKVBovNP0RuURvl2U6HvE3sNi7A941x60 vJuVwO69fKu4O9r2TONGlQAyOKX+lOCsLtAdBTtlle+9tEFjBxEvImuabh5UABXkM9jxn4dY31a LszC5aCoIT1ePdJUb3u94ErUr0RtHomfQvUhY4m7eqs6bBhPjcejhO7PUXcy4Lys7XznNXEM26A == X-Received: by 2002:a5d:4f09:0:b0:236:587a:61b2 with SMTP id c9-20020a5d4f09000000b00236587a61b2mr4837813wru.703.1668789783288; Fri, 18 Nov 2022 08:43:03 -0800 (PST) X-Google-Smtp-Source: AA0mqf6KiI4q5+z0TlyVCflD9NzXlW/ByBwHBI6YoLmo15RI+UnQ9Y/Qq+oLJZ8+BX/w/0EPBH/I2w== X-Received: by 2002:a5d:4f09:0:b0:236:587a:61b2 with SMTP id c9-20020a5d4f09000000b00236587a61b2mr4837802wru.703.1668789782914; Fri, 18 Nov 2022 08:43:02 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id i6-20020a05600c354600b003cf894c05e4sm9859750wmq.22.2022.11.18.08.43.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:02 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 1/7] gdb/remote: remove some manual reference count handling Date: Fri, 18 Nov 2022 16:42:52 +0000 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" While working on some other target_ops reference count related code, I spotted that in remote.c we do some manual reference count handling, i.e. we call target_ops::incref and decref_target (which wraps target_ops::decref). I think it would be better to make use of gdb::ref_ptr to automate the reference count management. So, this commit updates scoped_mark_target_starting in two ways, first, I use gdb::ref_ptr to handle the reference counts. Then, instead of using the scoped_mark_target_starting constructor and destructor to set and reset the starting_up flag, I now use a scoped_restore_tmpl object to set and restore the flag. The above changes mean that the scoped_mark_target_starting destructor can be completely removed, and the constructor body is now empty. I've also fixed a typo in the class comment. The only change in behaviour after this commit is that previously we didn't care what the value of starting_up was, we just set it to true in the constructor and false in the destructor. Now, I assert that the flag is initially false, then set the flag true when the scoped_mark_target_starting is created. As the starting_up flag is initialized to false then, for the assert to fire, we would need to recursively enter remote_target::start_remote_1, which I don't think is something we should be doing, so I think the new assert is an improvement. --- gdb/remote.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index 5118ecd0a31..24da3d544d5 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -4702,7 +4702,7 @@ remote_target::process_initial_stop_replies (int from_tty) } } -/* Mark a remote_target as marking (by setting the starting_up flag within +/* Mark a remote_target as starting (by setting the starting_up flag within its remote_state) for the lifetime of this object. The reference count on the remote target is temporarily incremented, to prevent the target being deleted under our feet. */ @@ -4712,26 +4712,32 @@ struct scoped_mark_target_starting /* Constructor, TARGET is the target to be marked as starting, its reference count will be incremented. */ scoped_mark_target_starting (remote_target *target) - : m_remote_target (target) - { - m_remote_target->incref (); - remote_state *rs = m_remote_target->get_remote_state (); - rs->starting_up = true; - } + : m_remote_target (remote_target_ref::new_reference (target)), + m_restore_starting_up (set_starting_up_flag (target)) + { /* Nothing. */ } + +private: - /* Destructor, mark the target being worked on as no longer starting, and - decrement the reference count. */ - ~scoped_mark_target_starting () + /* Helper function, set the starting_up flag on TARGET and return an + object which, when it goes out of scope, will restore the previous + value of the starting_up flag. */ + static scoped_restore_tmpl + set_starting_up_flag (remote_target *target) { - remote_state *rs = m_remote_target->get_remote_state (); - rs->starting_up = false; - decref_target (m_remote_target); + remote_state *rs = target->get_remote_state (); + gdb_assert (!rs->starting_up); + return make_scoped_restore (&rs->starting_up, true); } -private: + /* A gdb::ref_ptr pointer to a remote_target. */ + using remote_target_ref = gdb::ref_ptr; + + /* A reference to the target on which we are operating. */ + remote_target_ref m_remote_target; - /* The target on which we are operating. */ - remote_target *m_remote_target; + /* An object which restores the previous value of the starting_up flag + when it goes out of scope. */ + scoped_restore_tmpl m_restore_starting_up; }; /* Helper for remote_target::start_remote, start the remote connection and From patchwork Fri Nov 18 16:42:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60844 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 583D73842308 for ; Fri, 18 Nov 2022 16:45:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 583D73842308 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789936; bh=9Lhma4oYYhmfb1bNXAou5HMDnp3fe2lgTdoACa+UU7Y=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=yREUpTLSExr/PPRhZlonbukjAHsSr/Iao5ziPio5AML6kNkuNblmOWpF/jM9ZQU+3 YkJigfqgMrjaPU+4gzwq7CuhaNlCBWkWod1PJVhRYoosSVsbVrQlAt18fPG67569df QoBs6JXm6FasTu94vcl9jfHed9GrA9q8Ozxibvbk= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id D627C3851885 for ; Fri, 18 Nov 2022 16:43:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D627C3851885 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-101-2SCOeFMKPY6Nqcxn1PCerQ-1; Fri, 18 Nov 2022 11:43:06 -0500 X-MC-Unique: 2SCOeFMKPY6Nqcxn1PCerQ-1 Received: by mail-wm1-f69.google.com with SMTP id bg25-20020a05600c3c9900b003cf3ed7e27bso2493625wmb.4 for ; Fri, 18 Nov 2022 08:43:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9Lhma4oYYhmfb1bNXAou5HMDnp3fe2lgTdoACa+UU7Y=; b=1U9amRloKu12n6k+AL/swuaPh3SHyC00pG5nO2UP7OhjWXWkEjiYi0Xlx+St+N1nJ1 LhptReKdlKWtRGzm/pBGE532fZMRCrsAYaT+qCpLkFuhmkT80FmchPJlOnEfGt7CkpFO A27nFxKFrd7r+JY3ibr1G0/2v4KczMhgyy+JDWHXEA4kP2NP5Sa3xzSmJkUipIp/jkqu +WLCqH9puiaz3eRUaBKPZFWe9igZAzlJp5FIDHaoc4ctbAWtIeyt5SakMS+ujSvLZ/ut 0GA9KYx9P5e1o1kp8EgztDwYO5T6g+N5884TmDKIEmwTD9yMwTlRa3bANJGIIefxdijZ Mk6A== X-Gm-Message-State: ANoB5plJLvsatMM2Sr7elz8Hu2dFQbyynZsN34cMODGGxbcHdMIzcPxH UIIPFGxtFK1RL0NVlCYoGHnIewjefs2FmTNAZ3BvYLpXYszZbLdadQu+3FG7si6Q5h5SlhoEG4k ih/vxzTqQM4RpNjEtQ807BC8f2P541dv0KLfLaAGKPzk44VqCpxKMZMl1RIbz32Pk/CxhV7TReQ == X-Received: by 2002:adf:f951:0:b0:23a:2311:b35 with SMTP id q17-20020adff951000000b0023a23110b35mr4706089wrr.183.1668789784842; Fri, 18 Nov 2022 08:43:04 -0800 (PST) X-Google-Smtp-Source: AA0mqf66i1ZDuuRvTSwECeqYw3vvCe7EwqAolt415GUPfzXBOA7G+cpCNLNlayZEIyVoicYiSZDKog== X-Received: by 2002:adf:f951:0:b0:23a:2311:b35 with SMTP id q17-20020adff951000000b0023a23110b35mr4706074wrr.183.1668789784531; Fri, 18 Nov 2022 08:43:04 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id w3-20020a5d6803000000b00228d67db06esm3980872wru.21.2022.11.18.08.43.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:04 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 2/7] gdb: remove decref_target Date: Fri, 18 Nov 2022 16:42:53 +0000 Message-Id: <7c87022362c12d14247e3106f12018c0759848a1.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" The decref_target function is not really needed. Calling target_ops::decref will just redirect to decref_target anyway, so why not just rename decref_target to target_ops::decref? That's what this commit does. It's not exactly renaming to target_ops::decref, because the decref functionality is handled by a policy class, so the new name is now target_ops_ref_policy::decref. There should be no user visible change after this commit. --- gdb/target.c | 2 +- gdb/target.h | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/gdb/target.c b/gdb/target.c index 74925e139dc..d7f742c83ec 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1157,7 +1157,7 @@ to_execution_direction must be implemented for reverse async"); /* See target.h. */ void -decref_target (target_ops *t) +target_ops_ref_policy::decref (target_ops *t) { t->decref (); if (t->refcount () == 0) diff --git a/gdb/target.h b/gdb/target.h index 28aa9273893..0f5038fb9b2 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1337,9 +1337,6 @@ struct target_ops_deleter /* A unique pointer for target_ops. */ typedef std::unique_ptr target_ops_up; -/* Decref a target and close if, if there are no references left. */ -extern void decref_target (target_ops *t); - /* A policy class to interface gdb::ref_ptr with target_ops. */ struct target_ops_ref_policy @@ -1349,10 +1346,9 @@ struct target_ops_ref_policy t->incref (); } - static void decref (target_ops *t) - { - decref_target (t); - } + /* Decrement the reference count on T, and, if the reference count + reaches zero, close the target. */ + static void decref (target_ops *t); }; /* A gdb::ref_ptr pointer to a target_ops. */ From patchwork Fri Nov 18 16:42:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60845 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 701C138432F3 for ; Fri, 18 Nov 2022 16:46:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 701C138432F3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789966; bh=zhKO8YyF8e4ph6FmY+aAXwQk7/8dxwmLuvNTK7HZpO4=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=pFDz3bCliLj8G77IR9WtmnSKDhkYdGByvCvqNK3L8joWKnCtIzw0sYgGjT6RCZx9E MFqguyWe1PeI+Ui14hyCFfdRNQdiT9Z97JE3ojCLuPJDRn6N/KvQvGSkhFEJwhNcKF 6W+RLVZ+T2TvYtrx7wzmQfNgIj6jG8SKYERXjnBc= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 98D7D3853D6E for ; Fri, 18 Nov 2022 16:43:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 98D7D3853D6E Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-295-d2qhHBdVNvOTcOBa00I-qw-1; Fri, 18 Nov 2022 11:43:08 -0500 X-MC-Unique: d2qhHBdVNvOTcOBa00I-qw-1 Received: by mail-wr1-f69.google.com with SMTP id k1-20020adfb341000000b00238745c9b1aso1781552wrd.5 for ; Fri, 18 Nov 2022 08:43:08 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zhKO8YyF8e4ph6FmY+aAXwQk7/8dxwmLuvNTK7HZpO4=; b=lkJz8RVbwavhepI0VZaXOkObot7R7s1V6os+3LqBS/GdduJ86x3dQfcC2uwHqfUdiP hVYIAM78U6FGoiXxgQ6aUp3y+pyssyN+/BQcJkFevwfWSX4pXC/u8R8UTwHiyo4BRqaq G5vXrJzafrpTh3h+8f1sTsehfwV7YOWyyd2IuhciRE5sa6zo6WL05yXx7PDwfmUPxRhA oyCQseOWKYtMlQ6f6a0K2iDrQBvIqnro8MyRHKbwtftZzsSkwIkmGZvs1VV93JdxE3aS qebTrkVVWnlhVMNJ0DT1MUtAhcixcbsBXRK98FX1BFb5kkSONNLOu1pGf8QqvdlTgewH Sh/Q== X-Gm-Message-State: ANoB5pmY8jlrCDi9sqxe/emeId6AoMXp0OGV87Ox6NH/zJhsrKwCRZS1 9nXq0wwSHy/R0FesvMg7+82F9Wimg6r4L7OYvO+btM/MLu57uUDdf6n55pBm/kg/Lq5H1DorVGe Ga5t/qDRI6D6rZOgFyrG9UuvBLjZTKxECZUFC9widtPs215EPKNuUNnna7kgJOJBs8BnJ7QQAqA == X-Received: by 2002:a1c:6a04:0:b0:3cf:77cc:5f65 with SMTP id f4-20020a1c6a04000000b003cf77cc5f65mr5547556wmc.25.1668789786651; Fri, 18 Nov 2022 08:43:06 -0800 (PST) X-Google-Smtp-Source: AA0mqf5xE2+oz3+0PAvvtxVKRUs60akyf5PCDpR5SGHzJJFztKDroJ3o/Mfhw/LAXU8LmDhgfhE6TQ== X-Received: by 2002:a1c:6a04:0:b0:3cf:77cc:5f65 with SMTP id f4-20020a1c6a04000000b003cf77cc5f65mr5547531wmc.25.1668789786123; Fri, 18 Nov 2022 08:43:06 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id n14-20020a05600c3b8e00b003b4c979e6bcsm10759284wms.10.2022.11.18.08.43.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:05 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 3/7] gdb: have target_stack automate reference count handling Date: Fri, 18 Nov 2022 16:42:54 +0000 Message-Id: <55a15f6fbd7737801a38b561c39cd6736da2a0eb.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This commit changes the target_stack class from using a C style array of 'target_ops *' to using a C++ std::array. The benefit of this change is that some of the reference counting of target_ops objects is now done automatically. This commit fixes a crash in gdb.python/py-inferior.exp where GDB crashes at exit, leaving a core file behind. The crash occurs in connpy_connection_dealloc, and is actually triggered by this assert: gdb_assert (conn_obj->target == nullptr); Now a little aside... ... the assert is never actually printed, instead GDB crashes due to calling a pure virtual function. The backtrace at the point of crash looks like this: #7 0x00007fef7e2cf747 in std::terminate() () from /lib64/libstdc++.so.6 #8 0x00007fef7e2d0515 in __cxa_pure_virtual () from /lib64/libstdc++.so.6 #9 0x0000000000de334d in target_stack::find_beneath (this=0x4934d78, t=0x2bda270 ) at ../../s> #10 0x0000000000df4380 in inferior::find_target_beneath (this=0x4934b50, t=0x2bda270 ) at ../.> #11 0x0000000000de2381 in target_ops::beneath (this=0x2bda270 ) at ../../src/gdb/target.c:3047 #12 0x0000000000de68aa in target_ops::supports_terminal_ours (this=0x2bda270 ) at ../../src/gd> #13 0x0000000000dde6b9 in target_supports_terminal_ours () at ../../src/gdb/target.c:1112 #14 0x0000000000ee55f1 in internal_vproblem(internal_problem *, const char *, int, const char *, typedef __va_li> Notice in frame #12 we called target_ops::supports_terminal_ours, however, this is the_dummy_target, which is of type dummy_target, and so we should have called dummy_target::supports_terminal_ours. I believe the reason we ended up in the wrong implementation of supports_terminal_ours (which is a virtual function) is because we made the call during GDB's shut-down, and, I suspect, the vtables were in a weird state. Anyway, the point of this patch is not to fix GDB's ability to print an assert during exit, but to address the root cause of the assert. With that aside out of the way, we can return to the main story... Connections are represented in Python with gdb.TargtetConnection objects (or its sub-classes). The assert in question confirms that when a gdb.TargtetConnection is deallocated, the underlying GDB connection has itself been removed from GDB. If this is not true then we risk creating multiple different gdb.TargtetConnection objects for the same connection, which would be bad. To ensure that we have one gdb.TargtetConnection object for each connection, the all_connection_objects map exists, this maps the process_stratum_target object (the connection) to the gdb.TargtetConnection object that represents the connection. When a connection is removed in GDB the connection_removed observer fires, which we catch with connpy_connection_removed, this function then sets conn_obj->target to nullptr, and removes the corresponding entry from the all_connection_objects map. The first issue here is that connpy_connection_dealloc is being called as part of GDB's exit code, which is run after the Python interpreter has been shut down. The connpy_connection_dealloc function is used to deallocate the gdb.TargtetConnection Python object. Surely it is wrong for us to be deallocating Python objects after the interpreter has been shut down. The reason why connpy_connection_dealloc is called during GDB's exit is that the global all_connection_objects map is still holding a reference to the gdb.TargtetConnection object. When the map is destroyed during GDB's exit, the gdb.TargtetConnection objects within the map can finally be deallocated. The reason why all_connection_objects has contents when GDB exits, and the reason the assert fires, is that, when GDB exits, there are still some connections that have not yet been removed from GDB, that is, they have a non-zero reference count. If we take a look at quit_force (top.c) you can see that, for each inferior, we call pop_all_targets before we (later in the function) call do_final_cleanups. It is the do_final_cleanups call that is responsible for shutting down the Python interpreter. The pop_all_targets calls should, in theory, cause all the connections to be removed from GDB. That this isn't working indicates that some targets have a non-zero reference count even after this final pop_all_targets call, and indeed, when I debug GDB, that is what I see. I tracked the problem down to delete_inferior where we do some house keeping, and then delete the inferior object, which calls inferior::~inferior. In neither delete_inferior or inferior::~inferior do we call pop_all_targets, and it is this missing call that means we leak some references to the target_ops objects on the inferior's target_stack. In this commit I will provide a partial fix for the problem. I say partial fix, but this will actually be enough to resolve the crash. In a later commit I will provide the final part of the fix. As mentioned at the start of the commit message, this commit changes the m_stack in target_stack to hold target_ops_ref objects. This means that when inferior::~inferior is called, and m_stack is released, we automatically decrement the target_ops reference count. With this change in place we no longer leak any references, and now, in quit_force the final pop_all_targets calls will release the final references. This means that the targets will be correctly closed at this point, which means the connections will be removed from GDB and the Python objects deallocated before the Python interpreter shuts down. There's a slight oddity in target_stack::unpush, where we std::move the reference out of m_stack like this: auto ref = std::move (m_stack[stratum]); the `ref' isn't used explicitly, but it serves to hold the target_ops_ref until the end of the scope while allowing the m_stack entry to be reset back to nullptr. The alternative would be to directly set the m_stack entry to nullptr, like this: m_stack[stratum] = nullptr; The problem here is that when we set the m_stack entry to nullptr we first decrement the target_ops reference count, and then set the array entry to nullptr. If the decrement means that the target_ops object reaches a zero reference count then the target_ops object will be closed by calling target_close. In target_close we ensure that the target being closed is not in any inferiors target_stack. As we decrement before clearing, then this check in target_close will fail, and an assert will trigger. By using std::move to move the reference out of m_stack, this clears the m_stack entry, meaning the inferior no longer contains the target_ops in its target_stack. Now when the REF object goes out of scope and the reference count is decremented, target_close can run successfully. I've made use of the Python connection_removed listener API to add a test for this issue. The test installs a listener and then causes delete_inferior to be called, we can then see that the connection is then correctly removed (because the listener triggers). --- gdb/target.c | 43 +++++---- gdb/target.h | 4 +- .../gdb.python/py-connection-removed.exp | 92 +++++++++++++++++++ 3 files changed, 118 insertions(+), 21 deletions(-) create mode 100644 gdb/testsuite/gdb.python/py-connection-removed.exp diff --git a/gdb/target.c b/gdb/target.c index d7f742c83ec..75bc6c680d8 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1173,23 +1173,28 @@ target_ops_ref_policy::decref (target_ops *t) void target_stack::push (target_ops *t) { - t->incref (); + /* We must create a new reference first. It is possible that T is + already pushed on this target stack, in which case we will first + unpush it below, before re-pushing it. If we don't increment the + reference count now, then when we unpush it, we might end up deleting + T, which is not good. */ + auto ref = target_ops_ref::new_reference (t); strata stratum = t->stratum (); - if (stratum == process_stratum) - connection_list_add (as_process_stratum_target (t)); - /* If there's already a target at this stratum, remove it. */ - if (m_stack[stratum] != NULL) - unpush (m_stack[stratum]); + if (m_stack[stratum].get () != nullptr) + unpush (m_stack[stratum].get ()); /* Now add the new one. */ - m_stack[stratum] = t; + m_stack[stratum] = std::move (ref); if (m_top < stratum) m_top = stratum; + + if (stratum == process_stratum) + connection_list_add (as_process_stratum_target (t)); } /* See target.h. */ @@ -1214,19 +1219,19 @@ target_stack::unpush (target_ops *t) return false; } - /* Unchain the target. */ - m_stack[stratum] = NULL; - if (m_top == stratum) m_top = this->find_beneath (t)->stratum (); - /* Finally close the target, if there are no inferiors - referencing this target still. Note we do this after unchaining, - so any target method calls from within the target_close - implementation don't end up in T anymore. Do leave the target - open if we have are other inferiors referencing this target - still. */ - decref_target (t); + /* Move the target reference off the target stack, this sets the pointer + held in m_stack to nullptr, and places the reference in ref. When + ref goes out of scope its reference count will be decremented, which + might cause the target to close. + + We have to do it this way, and not just set the value in m_stack to + nullptr directly, because doing so would decrement the reference + count first, which might close the target, and closing the target + does a check that the target is not on any inferiors target_stack. */ + auto ref = std::move (m_stack[stratum]); return true; } @@ -3598,8 +3603,8 @@ target_stack::find_beneath (const target_ops *t) const { /* Look for a non-empty slot at stratum levels beneath T's. */ for (int stratum = t->stratum () - 1; stratum >= 0; --stratum) - if (m_stack[stratum] != NULL) - return m_stack[stratum]; + if (m_stack[stratum].get () != NULL) + return m_stack[stratum].get (); return NULL; } diff --git a/gdb/target.h b/gdb/target.h index 0f5038fb9b2..68446a39c1b 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1385,7 +1385,7 @@ class target_stack { return at (t->stratum ()) == t; } /* Return the target at STRATUM. */ - target_ops *at (strata stratum) const { return m_stack[stratum]; } + target_ops *at (strata stratum) const { return m_stack[stratum].get (); } /* Return the target at the top of the stack. */ target_ops *top () const { return at (m_top); } @@ -1400,7 +1400,7 @@ class target_stack /* The stack, represented as an array, with one slot per stratum. If no target is pushed at some stratum, the corresponding slot is null. */ - target_ops *m_stack[(int) debug_stratum + 1] {}; + std::array m_stack; }; /* Return the dummy target. */ diff --git a/gdb/testsuite/gdb.python/py-connection-removed.exp b/gdb/testsuite/gdb.python/py-connection-removed.exp new file mode 100644 index 00000000000..6a0dbd17fe0 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-connection-removed.exp @@ -0,0 +1,92 @@ +# Copyright (C) 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Check that the gdb.connect_removed event triggers when we expect it +# too. +# +# Checking this event has wider implications that simply some corner +# of the Python API working or not. The connection_removed event +# triggers when the reference count of a process_stratum_target +# reaches zero. If these events stop triggering when expected then +# GDB might be getting the reference counting on target_ops objects +# wrong. + +load_lib gdb-python.exp + +standard_testfile py-connection.c + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +if ![runto_main] then { + return 0 +} + +# Register a callback that will trigger when a connection is removed +# (deleted) within GDB. +gdb_test_multiline "Add connection_removed event" \ + "python" "" \ + "def connection_removed_handler(event):" "" \ + " num = event.connection.num" "" \ + " type = event.connection.type" "" \ + " print('Connection %d (%s) removed' % (num, type))" "" \ + "gdb.events.connection_removed.connect (connection_removed_handler)" "" \ + "end" "" + +if { [target_info exists gdb_protocol] } { + if { [target_info gdb_protocol] == "extended-remote" } { + set connection_type "extended-remote" + } else { + set connection_type "remote" + } +} else { + set connection_type "native" +} + +# Add an inferior that shares a connection with inferior 1. +gdb_test "add-inferior" "Added inferior 2 on connection 1 \[^\r\n\]+" + +# Add an inferior with no connection. +gdb_test "add-inferior -no-connection" "Added inferior 3" + +# Kill the first inferior. If we are using the plain 'remote' protocol then +# it as this point that the remote target connection is removed. For the +# 'extended-remote' and 'native' targets the connection is removed later. +if { $connection_type == "remote" } { + gdb_test "with confirm off -- kill" \ + "Connection 1 \\(remote\\) removed\r\n.*" "kill inferior" +} else { + gdb_test "with confirm off -- kill" "" "kill inferior" +} + +# Switch to inferior 3 (the one with no connection). +gdb_test "inferior 3" + +# Remove inferior 1, not expecting anything interesting at this point. +gdb_test_no_output "remove-inferiors 1" + +# Now removed inferior 2. For the 'remote' target the connection has +# already been removed (see above), but for 'extended-remote' and 'native' +# targets, it is at this point that the connection is removed. +if { $connection_type == "remote" } { + gdb_test_no_output "remove-inferiors 2" +} else { + gdb_test "remove-inferiors 2" \ + "Connection 1 \\(${connection_type}\\) removed" +} From patchwork Fri Nov 18 16:42:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60846 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AD6E83839D8D for ; Fri, 18 Nov 2022 16:46:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AD6E83839D8D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789997; bh=gmM9wWh1uSCpmrBLG8Lj2WZdjlA1uHfDKArrCa8bCeY=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=yyVUDficF6c0H+Qp7Ynon+A5z2AIFUvSArlNGoTe8INyquliegsLMgLQetPfy/wCJ 8b1x0/a3LLDnSEpBC2mX0N486CueuLC4ldG3Wq4eaVWswWppKBd/QUBHh2TKy3L8gr F7ViajYH/X7aCVDNZt38vTNR8728I0Zst8QCiawU= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id BF4D2384F6FB for ; Fri, 18 Nov 2022 16:43:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org BF4D2384F6FB Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-483-eul2Si6XOjq3aNbVILj7Nw-1; Fri, 18 Nov 2022 11:43:09 -0500 X-MC-Unique: eul2Si6XOjq3aNbVILj7Nw-1 Received: by mail-wm1-f70.google.com with SMTP id o5-20020a05600c510500b003cfca1a327fso2488682wms.8 for ; Fri, 18 Nov 2022 08:43:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gmM9wWh1uSCpmrBLG8Lj2WZdjlA1uHfDKArrCa8bCeY=; b=KsMwoqJN1wZgCrfFvyHNOPt+k99GIit5tl4OETxuhWyR+Gd3lVfAQ9AZkfcW1Oomc+ zwFWJnnjd1Y7U4Yqjk4b+Mu67P84ysNMB5M7c+9+sGTJe8P1tPjZ3QxstK32iBDLngRv GzpywLWsMxZS6OIzjoyHLed8+ORs7kZpsA3NQb6/8qlchTfS8LIBeKC3O0/mOWcxrOLu vdgCo8FEakSTCP5keVt7VkurYrxTEQjVeALpKsNiHz3cPyxsZam2D/IMf7mgWIvbRYCA VlBYosvgVH9FpssYnKG7ql1vuqazXFJK2K40NK0qgSHh6Y8JwU6JOJXNrHhd2PVdfDCq ZDLA== X-Gm-Message-State: ANoB5pn/CMcn3tkB00sKKYUD1d74Y85R5D5uXATQpdEwwawKVtHzSv8/ w7Pze5ERnBt4fSOqMU2uU1vW8acTjtH+uB3TXlOsy2JGoWAwKJ66kgB9EICNC1/bGvSra8VZwTX lJ4WX86kHszGFvMT5K2cZFTCoH27bNZTLkpq5yMQ7krDHqvGgREg+UafwIN5ckR1X+/DO2puw9A == X-Received: by 2002:a05:600c:15d6:b0:3cf:54a5:b7ee with SMTP id v22-20020a05600c15d600b003cf54a5b7eemr8965044wmf.106.1668789788128; Fri, 18 Nov 2022 08:43:08 -0800 (PST) X-Google-Smtp-Source: AA0mqf4jeCBiCJRu8oDlJT1HgosouHeiZ7btOYM9lQcF6Vef67uUBVhgOptbq4HMDUsLB2nw1ta0Ew== X-Received: by 2002:a05:600c:15d6:b0:3cf:54a5:b7ee with SMTP id v22-20020a05600c15d600b003cf54a5b7eemr8965016wmf.106.1668789787763; Fri, 18 Nov 2022 08:43:07 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id t23-20020adfa2d7000000b0023662d97130sm4095994wra.20.2022.11.18.08.43.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:07 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 4/7] gdb: remove the pop_all_targets (and friends) global functions Date: Fri, 18 Nov 2022 16:42:55 +0000 Message-Id: <4b85a8b4e635dafa1ca18e3602ba04669876b6b4.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" This commit removes the global functions pop_all_targets, pop_all_targets_above, and pop_all_targets_at_and_above, and makes them methods on the inferior class. As the pop_all_targets functions will unpush each target, which decrements the targets reference count, it is possible that the target might be closed. Right now, closing a target, in some cases, depends on the current inferior being set correctly, that is, to the inferior from which the target was popped. To facilitate this I have used switch_to_inferior_no_thread within the new methods. Previously it was the responsibility of the caller to ensure that the correct inferior was selected. In a couple of places (event-top.c and top.c) I have been able to remove a previous switch_to_inferior_no_thread call. In remote_unpush_target (remote.c) I have left the switch_to_inferior_no_thread call as it is required for the generic_mourn_inferior call. --- gdb/event-top.c | 3 +-- gdb/inferior.c | 39 ++++++++++++++++++++++++++++++++++++++ gdb/inferior.h | 20 ++++++++++++++++++++ gdb/remote.c | 2 +- gdb/scoped-mock-context.h | 2 +- gdb/target.c | 40 +-------------------------------------- gdb/target.h | 11 ----------- gdb/top.c | 3 +-- 8 files changed, 64 insertions(+), 56 deletions(-) diff --git a/gdb/event-top.c b/gdb/event-top.c index 0e371194ee3..d858104c1e8 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -1293,10 +1293,9 @@ async_disconnect (gdb_client_data arg) for (inferior *inf : all_inferiors ()) { - switch_to_inferior_no_thread (inf); try { - pop_all_targets (); + inf->pop_all_targets (); } catch (const gdb_exception &exception) { diff --git a/gdb/inferior.c b/gdb/inferior.c index 7eb2bd97907..4bad2198af7 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -103,6 +103,45 @@ inferior::unpush_target (struct target_ops *t) return m_target_stack.unpush (t); } +/* See inferior.h. */ + +void inferior::unpush_target_and_assert (struct target_ops *target) +{ + gdb_assert (current_inferior () == this); + + if (!unpush_target (target)) + internal_error ("pop_all_targets couldn't find target %s\n", + target->shortname ()); +} + +/* See inferior.h. */ + +void inferior::pop_all_targets_above (enum strata stratum) +{ + /* Unpushing a target might cause it to close. Some targets currently + rely on the current_inferior being set for their ::close method, so we + temporarily switch inferior now. */ + scoped_restore_current_pspace_and_thread restore_pspace_and_thread; + switch_to_inferior_no_thread (this); + + while (top_target ()->stratum () > stratum) + unpush_target_and_assert (top_target ()); +} + +/* See inferior.h. */ + +void inferior::pop_all_targets_at_and_above (enum strata stratum) +{ + /* Unpushing a target might cause it to close. Some targets currently + rely on the current_inferior being set for their ::close method, so we + temporarily switch inferior now. */ + scoped_restore_current_pspace_and_thread restore_pspace_and_thread; + switch_to_inferior_no_thread (this); + + while (top_target ()->stratum () >= stratum) + unpush_target_and_assert (top_target ()); +} + void inferior::set_tty (std::string terminal_name) { diff --git a/gdb/inferior.h b/gdb/inferior.h index 69525a2e053..2917f42e624 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -377,6 +377,22 @@ class inferior : public refcounted_object, target_ops *top_target () { return m_target_stack.top (); } + /* Unpush all targets except the dummy target from m_target_stack. As + targets are removed from m_target_stack their reference count is + decremented, which may cause a target to close. */ + void pop_all_targets () + { pop_all_targets_above (dummy_stratum); } + + /* Unpush all targets above STRATUM from m_target_stack. As targets are + removed from m_target_stack their reference count is decremented, + which may cause a target to close. */ + void pop_all_targets_above (enum strata stratum); + + /* Unpush all targets at and above STRATUM from m_target_stack. As + targets are removed from m_target_stack their reference count is + decremented, which may cause a target to close. */ + void pop_all_targets_at_and_above (enum strata stratum); + /* Return the target at process_stratum level in this inferior's target stack. */ struct process_stratum_target *process_target () @@ -595,6 +611,10 @@ class inferior : public refcounted_object, registry registry_fields; private: + + /* Unpush TARGET and assert that it worked. */ + void unpush_target_and_assert (struct target_ops *target); + /* The inferior's target stack. */ target_stack m_target_stack; diff --git a/gdb/remote.c b/gdb/remote.c index 24da3d544d5..4db5fd18b14 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -5717,7 +5717,7 @@ remote_unpush_target (remote_target *target) for (inferior *inf : all_inferiors (target)) { switch_to_inferior_no_thread (inf); - pop_all_targets_at_and_above (process_stratum); + inf->pop_all_targets_at_and_above (process_stratum); generic_mourn_inferior (); } diff --git a/gdb/scoped-mock-context.h b/gdb/scoped-mock-context.h index a9895303015..87c1df0d206 100644 --- a/gdb/scoped-mock-context.h +++ b/gdb/scoped-mock-context.h @@ -71,7 +71,7 @@ struct scoped_mock_context ~scoped_mock_context () { inferior_list.erase (inferior_list.iterator_to (mock_inferior)); - pop_all_targets_at_and_above (process_stratum); + mock_inferior.pop_all_targets_at_and_above (process_stratum); } }; diff --git a/gdb/target.c b/gdb/target.c index 75bc6c680d8..b2af51551ba 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1236,44 +1236,6 @@ target_stack::unpush (target_ops *t) return true; } -/* Unpush TARGET and assert that it worked. */ - -static void -unpush_target_and_assert (struct target_ops *target) -{ - if (!current_inferior ()->unpush_target (target)) - { - gdb_printf (gdb_stderr, - "pop_all_targets couldn't find target %s\n", - target->shortname ()); - internal_error (_("failed internal consistency check")); - } -} - -void -pop_all_targets_above (enum strata above_stratum) -{ - while ((int) (current_inferior ()->top_target ()->stratum ()) - > (int) above_stratum) - unpush_target_and_assert (current_inferior ()->top_target ()); -} - -/* See target.h. */ - -void -pop_all_targets_at_and_above (enum strata stratum) -{ - while ((int) (current_inferior ()->top_target ()->stratum ()) - >= (int) stratum) - unpush_target_and_assert (current_inferior ()->top_target ()); -} - -void -pop_all_targets (void) -{ - pop_all_targets_above (dummy_stratum); -} - void target_unpusher::operator() (struct target_ops *ops) const { @@ -2530,7 +2492,7 @@ target_preopen (int from_tty) it doesn't (which seems like a win for UDI), remove it now. */ /* Leave the exec target, though. The user may be switching from a live process to a core of the same program. */ - pop_all_targets_above (file_stratum); + current_inferior ()->pop_all_targets_above (file_stratum); target_pre_inferior (from_tty); } diff --git a/gdb/target.h b/gdb/target.h index 68446a39c1b..547ee8a3bbd 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -2389,17 +2389,6 @@ extern void target_pre_inferior (int); extern void target_preopen (int); -/* Does whatever cleanup is required to get rid of all pushed targets. */ -extern void pop_all_targets (void); - -/* Like pop_all_targets, but pops only targets whose stratum is at or - above STRATUM. */ -extern void pop_all_targets_at_and_above (enum strata stratum); - -/* Like pop_all_targets, but pops only targets whose stratum is - strictly above ABOVE_STRATUM. */ -extern void pop_all_targets_above (enum strata above_stratum); - extern CORE_ADDR target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset); diff --git a/gdb/top.c b/gdb/top.c index e9794184f07..f5fc7276ac7 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1845,10 +1845,9 @@ quit_force (int *exit_arg, int from_tty) them all out. */ for (inferior *inf : all_inferiors ()) { - switch_to_inferior_no_thread (inf); try { - pop_all_targets (); + inf->pop_all_targets (); } catch (const gdb_exception &ex) { From patchwork Fri Nov 18 16:42:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60842 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E7E5E383F2EC for ; Fri, 18 Nov 2022 16:44:39 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E7E5E383F2EC DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789879; bh=Ujf7l89RFOdOWL4M9S+ZuSNG5UVs/Xtla4pJEA3y2qw=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=takSnV5dnewMjhbYzXEMUxM1wF5K8+nyq3i3Lt6dC3f6bT0asU/Uqs4C49A4I/r5I zkhZSHblwPNGrzG7tQCjETxXmplFAkQVvR+7yZHQYaUe7MwwqIAQ8U1/CHCsLdlTO1 FnEKS7eJpoNrhDl+rETecPXqMZFXYKFNaSRhOXC8= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id A3FD4384F6C6 for ; Fri, 18 Nov 2022 16:43:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A3FD4384F6C6 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-482--xrGR11iOrq336JElt045Q-1; Fri, 18 Nov 2022 11:43:11 -0500 X-MC-Unique: -xrGR11iOrq336JElt045Q-1 Received: by mail-wm1-f72.google.com with SMTP id bi19-20020a05600c3d9300b003cf9d6c4016so4698638wmb.8 for ; Fri, 18 Nov 2022 08:43:10 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ujf7l89RFOdOWL4M9S+ZuSNG5UVs/Xtla4pJEA3y2qw=; b=aVrW6ekeosKvn2e69Unms3L5Vd6WmDafxls0UhqGdUWMnuxkWbJMZl06KEzwoFys5C o26UbV7lKgtLOb4YFwxp0S9mI8AX7zhieJlnXrKddD98fx0+Nl9bKlEIU2GMOnnDrwHm 2VDp/1wC8MiCVjSgs7ewsk4icNBagD6uWdYuPR3Gro3cYDx1nCMWOanTS5Z41UD6C2bx GS/R8zj4V46213X0Gbeek/en1urPM8sYaaZqTm3nQ7Z07hLX0ki22wUnjHvDxPNaBbxg xWudvCSf9S9fdCUcLJ8IUBux65eoN+jZQBM7txj2RiQ/MmRamWVvvOSDG4oA+b9oBdRG KmfA== X-Gm-Message-State: ANoB5pl9H9HMcegfk5VW+IbkIT1oMl1uvLVdTCZop7QVPjZByvnD3eVI Slg1XkcF43sSlTgS5p8ryMVhMXiVm9zv7D5777xp9WDDP5Yt/kTvDqq8ltBichsSLl1BiibggP+ KMd7NYtH8J8C86p6S0eJo7ihZ/d8DUSMt2i/NgvWznVaLTKTeCFqdBftz60Ws0Gqmj0t+T8ZKpg == X-Received: by 2002:a5d:54d2:0:b0:241:c224:201e with SMTP id x18-20020a5d54d2000000b00241c224201emr2139829wrv.43.1668789789717; Fri, 18 Nov 2022 08:43:09 -0800 (PST) X-Google-Smtp-Source: AA0mqf7TjsjQyKzqGHA2AP0Q9UTldPb7SHIN47RDUhq2fZdX+saD9FnUe9Bpcj1qyi/tFkOGGRt7aw== X-Received: by 2002:a5d:54d2:0:b0:241:c224:201e with SMTP id x18-20020a5d54d2000000b00241c224201emr2139816wrv.43.1668789789441; Fri, 18 Nov 2022 08:43:09 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id fc18-20020a05600c525200b003c71358a42dsm12833969wmb.18.2022.11.18.08.43.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:09 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 5/7] gdb: ensure all targets are popped before an inferior is destructed Date: Fri, 18 Nov 2022 16:42:56 +0000 Message-Id: <2e7400a931704b3b3f366d8c5b7c5d40c0931da9.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Now that the inferiors target_stack automatically manages target reference counts, we might think that we don't need to unpush targets when an inferior is deleted... ...unfortunately that is not the case. The inferior::unpush function can do some work depending on the type of target, so it is important that we still pass through this function. To ensure that this is the case, in this commit I've added an assert to inferior::~inferior that ensures the inferior's target_stack is empty (except for the ever present dummy_target). I've then added a pop_all_targets call to delete_inferior, otherwise the new assert will fire in, e.g. the gdb.python/py-inferior.exp test. --- gdb/inferior.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/gdb/inferior.c b/gdb/inferior.c index 4bad2198af7..f4b9828a425 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -70,6 +70,15 @@ inferior::~inferior () { inferior *inf = this; + /* Before the inferior is deleted, all target_ops should be popped from + the target stack, this leaves just the dummy_target behind. If this + is not done, then any target left in the target stack will be left + with an artificially high reference count. As the dummy_target is + still on the target stack then we are about to loose a reference to + that target, leaving its reference count artificially high. However, + this is not critical as the dummy_target is a singleton. */ + gdb_assert (m_target_stack.top ()->stratum () == dummy_stratum); + m_continuations.clear (); target_desc_info_free (inf->tdesc_info); } @@ -230,6 +239,12 @@ delete_inferior (struct inferior *inf) gdb::observers::inferior_removed.notify (inf); + /* Pop all targets now, this ensures that inferior::unpush is called + correctly. As pop_all_targets ends up making a temporary switch to + inferior INF then we need to make this call before we delete the + program space, which we do below. */ + inf->pop_all_targets (); + /* If this program space is rendered useless, remove it. */ if (inf->pspace->empty ()) delete inf->pspace; From patchwork Fri Nov 18 16:42:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60843 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 92AA13839DB7 for ; Fri, 18 Nov 2022 16:44:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 92AA13839DB7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789882; bh=WZUuOCiTOxFarp3LlY+C9CwQpj5gZiOxE8L653t6ykI=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=x84nqdPsH+RdIJVSmJHzs6psfL+7t+o9ofJMfWd2gh7h86kcXUb7w4I6nQqMbNEyq Bnz1UvXxkkYH1DKPsrtksUjlszGzhnM9cYhEQkvfbaeFNNCp43xI4DUW51YLVs8XX3 Sb1mCCiWxdO6QQ30PgJ9H9QuU6upqrwIBq+g9lc8= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 460C4384F48C for ; Fri, 18 Nov 2022 16:43:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 460C4384F48C Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-145-2CHbb0sqOX-38S3wLu3wSQ-1; Fri, 18 Nov 2022 11:43:12 -0500 X-MC-Unique: 2CHbb0sqOX-38S3wLu3wSQ-1 Received: by mail-wm1-f72.google.com with SMTP id r186-20020a1c44c3000000b003d0005ff848so2396315wma.2 for ; Fri, 18 Nov 2022 08:43:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WZUuOCiTOxFarp3LlY+C9CwQpj5gZiOxE8L653t6ykI=; b=DgyS/zm7uxyonfv5VkJ5+AlleAaC/eEhEkYeXOZ0LMMzzMakqkfY17uipncFqh0Sl4 /YiKCsYLU3nLLFzVLv1GSlMRwHBRwSfAoPkJPhb+K1Xn62RiXISCAcvurkwBPI7Su+AX Sch57UpQptewtdPlIvtykYikCuC+ivp636pSLMJhnGbdC0n9fPoUzznFCQhGREbDgIBD dRaphtvFnYDzbNvGMuck5EmgTvgEQAivWSk2HABxdNSwSjUmM/ozHnhWlXr+3dkrqk1l O8gUy4DCfylmjFTVDwq3tjt0KArKAuaFEqtJdySjTPTIXGkaXtbeevYmSN3+jwim1vEQ GbIw== X-Gm-Message-State: ANoB5pl5zl+DZSwl54Xjaz9CutbMwUWp2K794xw7dj5wl98FA2IkR3kv l4K4USB+kX6NP5MzBaWBbh5WNqgdq+alrwPq0ZrECmVjqcLvznjko3DT7emvf0K+I3+CIliygpG KNerZ6WLItiXpUUlhjPxErvit7R8vhefn+r15yYdeB27Od97Z4FoGd5B+X2/lrrxzuivx9Nltrw == X-Received: by 2002:a1c:4c0c:0:b0:3cf:9881:e9d9 with SMTP id z12-20020a1c4c0c000000b003cf9881e9d9mr5576173wmf.6.1668789791091; Fri, 18 Nov 2022 08:43:11 -0800 (PST) X-Google-Smtp-Source: AA0mqf7ZISjEmImk8he11pPCUWMlBgmXc0c64VMHVktS29JTDbMDi+sxqiapblm4XpXxJLGqGFkb2Q== X-Received: by 2002:a1c:4c0c:0:b0:3cf:9881:e9d9 with SMTP id z12-20020a1c4c0c000000b003cf9881e9d9mr5576157wmf.6.1668789790793; Fri, 18 Nov 2022 08:43:10 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id n1-20020a5d6b81000000b00226dba960b4sm3989476wrx.3.2022.11.18.08.43.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:10 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 6/7] gdb/maint: add core file name to 'maint info program-spaces' output Date: Fri, 18 Nov 2022 16:42:57 +0000 Message-Id: <6e8ccd780e088af4a3e9f822aad10d1ff72132f9.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Each program space can have an associated core file. Include this information in the output of 'maint info program-spaces'. --- gdb/NEWS | 4 ++++ gdb/doc/gdb.texinfo | 8 ++++++-- gdb/progspace.c | 18 ++++++++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 424e5ffd829..8176940ae1a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -146,6 +146,10 @@ maintenance info line-table entry corresponds to an address where a breakpoint should be placed to be at the first instruction past a function's prologue. +maintenance info program-spaces + This command now includes a 'Core File' column which indicates the + name of the core file associated with each program space. + * New targets GNU/Linux/LoongArch (gdbserver) loongarch*-*-linux* diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index bb7b2764408..566da9e7d92 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -3465,6 +3465,10 @@ the name of the executable loaded into the program space, with e.g., the @code{file} command. +@item +the name of the core file loaded into the program space, with e.g., +the @code{core-file} command. + @end enumerate @noindent @@ -3477,7 +3481,7 @@ @smallexample (@value{GDBP}) maint info program-spaces - Id Executable + Id Executable Core File * 1 hello 2 goodbye Bound inferiors: ID 1 (process 21561) @@ -3491,7 +3495,7 @@ @smallexample (@value{GDBP}) maint info program-spaces - Id Executable + Id Executable Core File * 1 vfork-test Bound inferiors: ID 2 (process 18050), ID 1 (process 18045) @end smallexample diff --git a/gdb/progspace.c b/gdb/progspace.c index 90003d964fe..4f58d44a0e6 100644 --- a/gdb/progspace.c +++ b/gdb/progspace.c @@ -251,22 +251,30 @@ print_program_space (struct ui_out *uiout, int requested) { int count = 0; + /* Start with a minimum width of 17 for the executable name column. */ + size_t longest_exec_name = 17; + /* Compute number of pspaces we will print. */ for (struct program_space *pspace : program_spaces) { if (requested != -1 && pspace->num != requested) continue; + if (pspace->exec_filename != nullptr) + longest_exec_name = std::max (strlen (pspace->exec_filename.get ()), + longest_exec_name); + ++count; } /* There should always be at least one. */ gdb_assert (count > 0); - ui_out_emit_table table_emitter (uiout, 3, count, "pspaces"); + ui_out_emit_table table_emitter (uiout, 4, count, "pspaces"); uiout->table_header (1, ui_left, "current", ""); uiout->table_header (4, ui_left, "id", "Id"); - uiout->table_header (17, ui_left, "exec", "Executable"); + uiout->table_header (longest_exec_name, ui_left, "exec", "Executable"); + uiout->table_header (17, ui_left, "core", "Core File"); uiout->table_body (); for (struct program_space *pspace : program_spaces) @@ -291,6 +299,12 @@ print_program_space (struct ui_out *uiout, int requested) else uiout->field_skip ("exec"); + if (pspace->cbfd != nullptr) + uiout->field_string ("core", bfd_get_filename (pspace->cbfd.get ()), + file_name_style.style ()); + else + uiout->field_skip ("core"); + /* Print extra info that doesn't really fit in tabular form. Currently, we print the list of inferiors bound to a pspace. There can be more than one inferior bound to the same pspace, From patchwork Fri Nov 18 16:42:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 60840 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EB105384D9BB for ; Fri, 18 Nov 2022 16:43:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EB105384D9BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1668789833; bh=RowFyS30cFNkFkTCrfGg3xwPxZjPBleOywcZowwjeB8=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=wfho7802LPGJjiENgilEJ//FIC9mWnE4e6v1XSBFvT0gmZCnMWlk8c+EF7mOBMGDj nIBKCkc1qFVvTgaMB+H/f/HYhCqRGHreNPUqakStSGon2gZ2c4VY9HaJaKjSd12Vpm pRn8f9GXuU0qt7BSYMYvKF3hPJYgIfJyeGsd8trM= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 66C6D3852C63 for ; Fri, 18 Nov 2022 16:43:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 66C6D3852C63 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-122-T8c3nib4MJGkggGA43Ynww-1; Fri, 18 Nov 2022 11:43:15 -0500 X-MC-Unique: T8c3nib4MJGkggGA43Ynww-1 Received: by mail-wr1-f69.google.com with SMTP id v14-20020adf8b4e000000b0024174021277so1792299wra.13 for ; Fri, 18 Nov 2022 08:43:14 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RowFyS30cFNkFkTCrfGg3xwPxZjPBleOywcZowwjeB8=; b=ods3H5ZeG6Tkn62aWwwvAo0MgKxtwFMOIC2gkm7QapjVWg+52QicEMS+oixGEbG8tV ww+7Kf6RjXpNBtc4IOf+oidUiQO6SYoalOL/cGRRbPmJ2d/MXBmyNgzuZjgwfjQtsbff 1fjpfUVoqvgPjcXIBUEJuubxTl67jp6n+042bul5EXfLP3qAtryOKtDiwH0AGzbN/oRy D5NT88irOyWJOQIVC6H7rmjxko9UwSTTmS7cyGKeo05YRDkQ6gL2WO0zzSzWH+kfQPkd z849A9nmkwIPJbSpG3BRhxzXBTiD53v3cGo+afy2z0E865R6MByQIBkNUm7dl0zkjeaR oVZg== X-Gm-Message-State: ANoB5plkLxXqltm0W/hDPDZylTQ+vQUynx6QVCjIl3sNc30Tt84KYWnH ZYgqqJ8ne9Q75eKFcO5fvnrlTkHRaeFC49hWPrCLw7wr1DvwAyRLWV8qOL1xyL1uSQ3IBZXTE1k 5Ov62W4yp6a73TjKCyjroBaP7UR3L1iXFAdygBLftup7sdDCdFQ7B1N/G+hN+OHaGUqA+xx5GIw == X-Received: by 2002:a05:600c:292:b0:3cf:8203:1761 with SMTP id 18-20020a05600c029200b003cf82031761mr5704926wmk.64.1668789793222; Fri, 18 Nov 2022 08:43:13 -0800 (PST) X-Google-Smtp-Source: AA0mqf7AlQ4J5h0sQl+MgcE9y5Od8C94TNg2ATbl2DPNKVKbTz5IuEO/oWFPuLrfHaPmQ8pgRMjGug== X-Received: by 2002:a05:600c:292:b0:3cf:8203:1761 with SMTP id 18-20020a05600c029200b003cf82031761mr5704889wmk.64.1668789792552; Fri, 18 Nov 2022 08:43:12 -0800 (PST) Received: from localhost ([31.111.84.238]) by smtp.gmail.com with ESMTPSA id l12-20020a05600c2ccc00b003cf54b77bfesm9600219wmc.28.2022.11.18.08.43.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Nov 2022 08:43:12 -0800 (PST) To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv3 7/7] gdb: some process_stratum_target should not be shared Date: Fri, 18 Nov 2022 16:42:58 +0000 Message-Id: <577f2c47793acb501c2611c0e6c7ea379f774830.1668789658.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Andrew Burgess via Gdb-patches From: Andrew Burgess Reply-To: Andrew Burgess Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" When multi-target support was added to GDB, an assumption was made that all process_stratum_target sub-classes could be shared by multiple inferiors. For things like the Linux and FreeBSD native targets, as well as the remote target, this is absolutely true (or was made true). But some targets were never updated to be shareable, for example, the core_target, which is used when reading core-files, stores some of its state in the program_space, but also, the core-file and the executable being debugged are closely related. As each add-inferior call creates an inferior with a new program_space, and doesn't automatically copy the executable, or the current core-file, I don't think it really makes sense to "share" core_target objects between inferiors. Consider this session: $ gdb -q (gdb) file test1 Reading symbols from test1... (gdb) core-file core.test1.433190 [New LWP 433190] Core was generated by `./test1'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in foo () at test1.c:6 6 return *global_ptr; (gdb) add-inferior [New inferior 2] Added inferior 2 on connection 1 (core) (gdb) info inferiors Num Description Connection Executable * 1 process 433190 1 (core) /tmp/multi-core/test1 2 1 (core) (gdb) info connections Num What Description * 1 core Local core dump file (gdb) inferior 2 [Switching to inferior 2 [] ()] (gdb) file test2 Reading symbols from test2... (gdb) core-file core.test2.433203 [New LWP 433203] Core was generated by `./test2'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in main () at test2.c:6 6 return *global_ptr; (gdb) info inferiors Num Description Connection Executable 1 process 433190 1 (core) /tmp/multi-core/test1 * 2 process 433203 2 (core) /tmp/multi-core/test2 (gdb) info connections Num What Description 1 core Local core dump file * 2 core Local core dump file (gdb) After the 'add-inferior' the core_target connection is shared between the inferiors. However, as soon as the user sets up the core-file and executable in the new inferior a new core connection has been created. I think this behaviour might be confusing, so I'd like to have GDB not initially share the core connection. Instead, when the user tries to add the new inferior a warning is given, and the new inferior is created without a connection, like this: $ gdb -q (gdb) file test1 Reading symbols from test1... (gdb) core-file core.test1.433190 [New LWP 433190] Core was generated by `./test1'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000000000401111 in foo () at test1.c:6 6 return *global_ptr; (gdb) add-inferior [New inferior 2] warning: can't share connection 1 (core) between inferiors Added inferior 2 (gdb) info inferiors Num Description Connection Executable * 1 process 433190 1 (core) /tmp/multi-core/test1 2 (gdb) If the user explicitly asks for the new inferior to be created without a connection, then no warning will be given. At this point the user is free to setup inferior 2 with a different executable and core file (or to do anything they like with the inferior). In an earlier version of this patch I had GDB error instead of giving a warning. However, the error message ended up being something like: can't share connection ..... between inferiors, use -no-connection option to create an inferior without sharing a connection. but it seemed better to just create the inferior. I've updated the docs, and added a NEWS entry for the new warning. In the docs for clone-inferior I've added reference to -no-connection, which was previously missing. --- gdb/NEWS | 7 + gdb/corelow.c | 5 + gdb/doc/gdb.texinfo | 37 +++- gdb/inferior.c | 16 ++ gdb/inferior.h | 6 +- gdb/target.c | 14 ++ gdb/target.h | 8 + gdb/testsuite/gdb.multi/multi-core-files-1.c | 37 ++++ gdb/testsuite/gdb.multi/multi-core-files-2.c | 31 ++++ gdb/testsuite/gdb.multi/multi-core-files.exp | 172 +++++++++++++++++++ 10 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 gdb/testsuite/gdb.multi/multi-core-files-1.c create mode 100644 gdb/testsuite/gdb.multi/multi-core-files-2.c create mode 100644 gdb/testsuite/gdb.multi/multi-core-files.exp diff --git a/gdb/NEWS b/gdb/NEWS index 8176940ae1a..5c8dac12de7 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,13 @@ * New convenience variable $_inferior_thread_count contains the number of live threads in the current inferior. +* The add-inferior, clone-inferior, and MI -add-inferior commands will + now give a warning, and create the new inferior without a + connection, when the current inferior, at the time the command is + given, is a core-file target. The core-file target could never + really be shared between inferiors, GDB is now more vocal about what + is going on. + * New commands maintenance set ignore-prologue-end-flag on|off diff --git a/gdb/corelow.c b/gdb/corelow.c index 293bc8d4f59..4d8393a3587 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -128,6 +128,11 @@ class core_target final : public process_stratum_target /* See definition. */ void info_proc_mappings (struct gdbarch *gdbarch); + /* The core_target only works for the inferior in which it was initially + opened, and can't be copied to some other inferior's target_stack. */ + bool is_shareable () override + { return false; } + private: /* per-core data */ /* Get rid of the core inferior. */ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 566da9e7d92..bb33e60a22e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -3358,8 +3358,31 @@ remote} command to connect to some other @code{gdbserver} instance, use @code{run} to spawn a local program, etc. +Not all connections can be shared between inferiors. For example, the +@code{target core} target is unique for each inferior. That is, +multiple inferiors can use @code{target core} at the same time, but +each @code{target core} is different. If you try to +@code{add-inferior}, and the current inferior is @code{target core}, +then @value{GDBN} will give a warning and create the new inferior +without a connection, like this: + +@smallexample +(@value{GDBP}) file test1 +Reading symbols from test1... +(@value{GDBP}) target core core.test1.433190 +[New LWP 433190] +Core was generated by `./test1'. +Program terminated with signal SIGSEGV, Segmentation fault. +#0 0x0000000000401111 in foo () at test1.c:6 +6 return *global_ptr; +(@value{GDBP}) add-inferior +[New inferior 2] +warning: can't share connection 1 (core) between inferiors +Added inferior 2 +@end smallexample + @kindex clone-inferior -@item clone-inferior [ -copies @var{n} ] [ @var{infno} ] +@item clone-inferior [ -copies @var{n} ] [ -no-connection ] [ @var{infno} ] Adds @var{n} inferiors ready to execute the same program as inferior @var{infno}; @var{n} defaults to 1, and @var{infno} defaults to the number of the current inferior. This command copies the values of the @@ -3384,6 +3407,13 @@ You can now simply switch focus to inferior 2 and run it. +Like @code{add-inferior}, @code{clone-inferior} shares the connection +with the inferior @var{infno}. If the @var{-no-connection} option is +given, then the new inferior will be created without a connection. If +the connection of inferior @var{infno} can't be shared, then +@value{GDBN} will give a warning, and the new inferior will be created +without a connection. + @kindex remove-inferiors @item remove-inferiors @var{infno}@dots{} Removes the inferior or inferiors @var{infno}@dots{}. It is not @@ -37828,6 +37858,11 @@ @code{gdbserver} instance, use @code{-exec-run} to spawn a local program, etc. +If the connection of the current inferior cannot be shared, e.g.@: the +@code{-target-select core} target cannot be shared between inferiors, +then @value{GDBN} will give a warning and create the new inferior +without a connection. + The command response always has a field, @var{inferior}, whose value is the identifier of the thread group corresponding to the new inferior. diff --git a/gdb/inferior.c b/gdb/inferior.c index f4b9828a425..ec4c348f7e3 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -816,6 +816,22 @@ switch_to_inferior_and_push_target (inferior *new_inf, symbols. */ switch_to_inferior_no_thread (new_inf); + if (!no_connection && proc_target != nullptr + && !proc_target->is_shareable ()) + { + if (proc_target->connection_string () != nullptr) + warning (_("can't share connection %d (%s %s) between inferiors"), + proc_target->connection_number, + proc_target->shortname (), + proc_target->connection_string ()); + else + warning (_("can't share connection %d (%s) between inferiors"), + proc_target->connection_number, + proc_target->shortname ()); + + proc_target = nullptr; + } + /* Reuse the target for new inferior. */ if (!no_connection && proc_target != NULL) { diff --git a/gdb/inferior.h b/gdb/inferior.h index 2917f42e624..a312cd2b9bb 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -759,9 +759,9 @@ extern struct inferior *add_inferior_with_spaces (void); /* Print the current selected inferior. */ extern void print_selected_inferior (struct ui_out *uiout); -/* Switch to inferior NEW_INF, a new inferior, and unless - NO_CONNECTION is true, push the process_stratum_target of ORG_INF - to NEW_INF. */ +/* Switch to inferior NEW_INF, a new inferior, and unless NO_CONNECTION is + true, or the process_stratum_target of ORG_INF is not shareable, push + the process_stratum_target of ORG_INF to NEW_INF. */ extern void switch_to_inferior_and_push_target (inferior *new_inf, bool no_connection, inferior *org_inf); diff --git a/gdb/target.c b/gdb/target.c index b2af51551ba..ac0608645b4 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1187,6 +1187,12 @@ target_stack::push (target_ops *t) if (m_stack[stratum].get () != nullptr) unpush (m_stack[stratum].get ()); + /* If this target can't be shared, then check that the target doesn't + already appear on some other target stack. */ + if (!t->is_shareable ()) + for (inferior *inf : all_inferiors ()) + gdb_assert (!inf->target_is_pushed (t)); + /* Now add the new one. */ m_stack[stratum] = std::move (ref); @@ -3221,6 +3227,14 @@ target_ops::fileio_readlink (struct inferior *inf, const char *filename, /* See target.h. */ +bool +target_ops::is_shareable () +{ + return true; +} + +/* See target.h. */ + int target_fileio_open (struct inferior *inf, const char *filename, int flags, int mode, bool warn_if_slow, fileio_error *target_errno) diff --git a/gdb/target.h b/gdb/target.h index 547ee8a3bbd..30e5085a543 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -1321,6 +1321,14 @@ struct target_ops virtual bool store_memtags (CORE_ADDR address, size_t len, const gdb::byte_vector &tags, int type) TARGET_DEFAULT_NORETURN (tcomplain ()); + + /* Return true if this target can be shared on multiple target_stacks, + or false if this target should only appear on a single target_stack. + When this function returns false multiple separate instances of the + same target_ops sub-class can still appear on different + target_stacks, but the same concrete instance can only appear on a + single target_stack. */ + virtual bool is_shareable (); }; /* Deleter for std::unique_ptr. See comments in diff --git a/gdb/testsuite/gdb.multi/multi-core-files-1.c b/gdb/testsuite/gdb.multi/multi-core-files-1.c new file mode 100644 index 00000000000..f996973023e --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files-1.c @@ -0,0 +1,37 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +int +bar () +{ + abort (); + return 0; +} + +int +baz () +{ + return bar (); +} + +int +main () +{ + return baz (); +} diff --git a/gdb/testsuite/gdb.multi/multi-core-files-2.c b/gdb/testsuite/gdb.multi/multi-core-files-2.c new file mode 100644 index 00000000000..fb99e137c3f --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files-2.c @@ -0,0 +1,31 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +int +foo () +{ + abort (); + return 0; +} + +int +main () +{ + return foo (); +} diff --git a/gdb/testsuite/gdb.multi/multi-core-files.exp b/gdb/testsuite/gdb.multi/multi-core-files.exp new file mode 100644 index 00000000000..8c2610000a0 --- /dev/null +++ b/gdb/testsuite/gdb.multi/multi-core-files.exp @@ -0,0 +1,172 @@ +# Copyright 2022 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This script runs some basic tests that GDB can support multiple +# inferiors each debugging different core files. +# +# We also check the behaviour of GDB if the user attempts to clone or +# duplicate an inferior that is debugging a core file. + +standard_testfile -1.c -2.c + +set binfile1 "${binfile}-1" +set binfile2 "${binfile}-2" + +if {[build_executable "build first executable" $binfile1 $srcfile \ + debug] == -1} { + untested "failed to compile first executable" + return -1 +} + +if {[build_executable "build second executable" $binfile2 $srcfile2 \ + debug] == -1} { + untested "failed to compile second executable" + return -1 +} + +set corefile1 [core_find $binfile1] +set corefile2 [core_find $binfile2] +if { $corefile1 == "" || $corefile2 == "" } { + untested "Can't generate core files" + return +} + +# Start GDB, and load the first executable and corefile into the first +# inferior. +clean_restart ${binfile1} +gdb_test "core-file $corefile1" "Program terminated with .*" \ + "load core file" +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 1" + +# The native-extended-remote board connects to the remote target as +# soon as GDB is started, this means that connection 1 is to the +# remote target, and the core target we create below will be +# connection 2. +# +# In all other cases, the core target gets to be connection 1. +if { [target_info gdb_protocol] == "extended-remote"} { + set conn_num 2 +} else { + set conn_num 1 +} + +# Try to use add-inferior and clone-inferior to create new +# inferiors. In both cases this will try to share the core_target +# between inferior 1 and the new inferior. As the core_target can't +# be shared we should get a warning, and the inferior should be +# created without a connection. +gdb_test "add-inferior" \ + [multi_line \ + "\\\[New inferior 2\\\]" \ + "warning: can't share connection ${conn_num} \\(core\\) between inferiors" \ + "Added inferior 2"] +gdb_test "clone-inferior" \ + [multi_line \ + "\\\[New inferior 3\\\]" \ + "warning: can't share connection ${conn_num} \\(core\\) between inferiors" \ + "Added inferior 3"] + +# Check the MI -add-inferior command. Do this using interpreter-exec. +# We're not doing a full MI test here, just checking this one command. +gdb_test "interpreter-exec mi \"-add-inferior\"" \ + [multi_line \ + "~\"\\\[New inferior 4\\\]..\"" \ + "&\"warning: can't share connection ${conn_num} \\(core\\) between inferiors..\"" \ + "~\"Added inferior 4..\"" \ + "\\^done,inferior=\"\[^\"\]+\""] + +# Now check that none of the new inferiors have a connection. +gdb_test "info inferiors" \ + [multi_line \ + "\\*\\s+1\\s+\[^\r\n\]+\\s+${conn_num} \\(core\\)\\s+\[^\r\n\]+.*" \ + "\\s+2\\s+\\s+" \ + "\\s+3\\s+\\s+\[^\r\n\]+" \ + "\\s+4\\s+\\s+"] \ + "first info inferiors call" + +# Now use add-inferior and clone-inferior but this time with the +# -no-connection option, this should avoid issuing the warning. We +# also use interpreter-exec to test the MI version of this command. +gdb_test "add-inferior -no-connection" \ + [multi_line \ + "\\\[New inferior 5\\\]" \ + "Added inferior 5"] +gdb_test "clone-inferior -no-connection" \ + [multi_line \ + "\\\[New inferior 6\\\]" \ + "Added inferior 6"] +gdb_test "interpreter-exec mi \"-add-inferior --no-connection\"" \ + "\\\[New inferior 7\\\].*Added inferior 7.*" + +# Now check that none of the new inferiors have a connection. +gdb_test "info inferiors" \ + [multi_line \ + "\\*\\s+1\\s+\[^\r\n\]+\\s+${conn_num} \\(core\\)\\s+\[^\r\n\]+.*" \ + "\\s+2\\s+\\s+" \ + "\\s+3\\s+\\s+\[^\r\n\]+" \ + "\\s+4\\s+\\s+" \ + "\\s+5\\s+\\s+" \ + "\\s+6\\s+\\s+\[^\r\n\]+" \ + "\\s+7\\s+\\s+"] \ + "second info inferiors call" + +# Check after all the new inferiors have been created that we still +# only have a single connection. +gdb_test "info connections" \ + "\\*\\s+${conn_num}\\s+\\s+core\\s+Local core dump file\\s*" + +# Now switch to inferior 2 and load the second executable and core +# file. Check the backtrace for the presence of function 'foo', this +# indicates we are seeing the correct core file. +gdb_test "inferior 2" "Switching to inferior 2 .*" +gdb_test "file $binfile2" \ + "Reading symbols from .*" \ + "Loaded second test binary" +gdb_test "core-file $corefile2" \ + "Program terminated with signal SIGABRT, Aborted.*" \ + "Loaded second core file" +gdb_test "bt" "foo \\(\\) at .*" \ + "check backtrace in inferior 2" + +# Switch to inferior 3, this one was cloned from inferior 1, so is +# already debugging the first binary file. Check its backtrace for +# 'bar', which indicates we are debugging the correct core file. +gdb_test "inferior 3" "Switching to inferior 3 .*" +gdb_test "core-file $corefile1" \ + "Program terminated with signal SIGABRT, Aborted.*" \ + "Loaded first core file into inferior 3" +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 3" + +# Detach from some of the core files and delete some of the inferiors. +gdb_test "detach" "No core file now\\." \ + "detach from inferior 3 core file" +gdb_test "inferior 2" "Switching to inferior 2 .*" \ + "switch back to inferior 2" +gdb_test_no_output "remove-inferiors 3 4" + +# Now detach in inferior 2, and delete the inferior. +gdb_test "detach" "No core file now\\." \ + "detach from inferior 2 core file" +gdb_test "inferior 1" "Switching to inferior 1 .*" \ + "switch back to inferior 1" +gdb_test_no_output "remove-inferiors 2" + +# Finally, check that inferior 1 backtrace is still working. +gdb_test "bt" "bar \\(\\) at .*" \ + "check backtrace in inferior 1 again" +gdb_test "detach" "No core file now\\." \ + "detach from inferior 1 core file"