From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by sourceware.org (Postfix) with ESMTP id 62566385DC39 for ; Tue, 14 Apr 2020 17:54:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 62566385DC39 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-135-4f7BrABcPyaXbcK30mapdw-1; Tue, 14 Apr 2020 13:54:38 -0400 X-MC-Unique: 4f7BrABcPyaXbcK30mapdw-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2AE6A800D53 for ; Tue, 14 Apr 2020 17:54:37 +0000 (UTC) Received: from cascais.Home (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id B1B9D9F99D for ; Tue, 14 Apr 2020 17:54:36 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 02/28] gcore, handle exited threads better Date: Tue, 14 Apr 2020 18:54:08 +0100 Message-Id: <20200414175434.8047-3-palves@redhat.com> In-Reply-To: <20200414175434.8047-1-palves@redhat.com> References: <20200414175434.8047-1-palves@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-28.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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-List-Received-Date: Tue, 14 Apr 2020 17:54:45 -0000 An early (and since discarded) version of this series tried to make exited threads have distinct PTID between each other, and that change exposed a problem in linux-tdep.c... This was exposed by the gdb.threads/gcore-stale-thread.exp testcase, which is exactly about calling gcore with an exited thread selected: (gdb) [Thread 0x7ffff7fb6740 (LWP 31523) exited] PASS: gdb.threads/gcore-stale-thread.exp: continue to breakpoint: break-he= re gcore /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.threads= /gcore-stale-thread/gcore-stale-thread.core /home/pedro/gdb/binutils-gdb/build/../src/gdb/inferior.c:66: internal-erro= r: void set_current_inferior(inferior*): Assertion `inf !=3D NULL' failed. A problem internal to GDB has been detected, That was find_inferior_ptid being called on the "exited" ptid, which on that previous (and discarded attempt) had pid=3D=3D-1. The problem is that linux-tdep.c, where it looks for the signalled thread, isn't considering exited threads. Also, while at it, that code isn't considering multi-target either, since it is using iterate_over_threads which iterates over all threads of all targets. Fixed by switching to range-for iteration instead. gdb/ChangeLog: yyyy-mm-dd Pedro Alves =09* linux-tdep.c (find_signalled_thread(thread_info *,void *)): =09Delete. =09(find_signalled_thread()): New, factored out from =09linux_make_corefile_notes and adjusted to handle exited threads. =09(linux_make_corefile_notes): Adjust to use the new =09find_signalled_thread. --- gdb/linux-tdep.c | 60 +++++++++++++++++++++++++++++++---------------------= ---- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index f204831e39..3e39a54ba2 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1402,18 +1402,6 @@ linux_find_memory_regions (struct gdbarch *gdbarch, =09=09=09=09=09 &data); } =20 -/* Determine which signal stopped execution. */ - -static int -find_signalled_thread (struct thread_info *info, void *data) -{ - if (info->suspend.stop_signal !=3D GDB_SIGNAL_0 - && info->ptid.pid () =3D=3D inferior_ptid.pid ()) - return 1; - - return 0; -} - /* This is used to pass information from linux_make_mappings_corefile_notes through linux_find_memory_regions_full. */ @@ -1861,6 +1849,30 @@ linux_fill_prpsinfo (struct elf_internal_linux_prpsi= nfo *p) return 1; } =20 +/* Find the signalled thread. In case there's more than one signalled + thread, prefer the current thread, if it is signalled. If no + thread was signalled, default to the current thread, unless it has + exited, in which case return NULL. */ + +static thread_info * +find_signalled_thread () +{ + thread_info *curr_thr =3D inferior_thread (); + if (curr_thr->state !=3D THREAD_EXITED + && curr_thr->suspend.stop_signal !=3D GDB_SIGNAL_0) + return curr_thr; + + for (thread_info *thr : current_inferior ()->non_exited_threads ()) + if (thr->suspend.stop_signal !=3D GDB_SIGNAL_0) + return thr; + + /* Default to the current thread, unless it has exited. */ + if (curr_thr->state !=3D THREAD_EXITED) + return curr_thr; + + return nullptr; +} + /* Build the note section for a corefile, and return it in a malloc buffer. */ =20 @@ -1870,7 +1882,6 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, b= fd *obfd, int *note_size) struct linux_corefile_thread_data thread_args; struct elf_internal_linux_prpsinfo prpsinfo; char *note_data =3D NULL; - struct thread_info *curr_thr, *signalled_thr; =20 if (! gdbarch_iterate_over_regset_sections_p (gdbarch)) return NULL; @@ -1898,26 +1909,21 @@ linux_make_corefile_notes (struct gdbarch *gdbarch,= bfd *obfd, int *note_size) } =20 /* Like the kernel, prefer dumping the signalled thread first. - "First thread" is what tools use to infer the signalled thread. - In case there's more than one signalled thread, prefer the - current thread, if it is signalled. */ - curr_thr =3D inferior_thread (); - if (curr_thr->suspend.stop_signal !=3D GDB_SIGNAL_0) - signalled_thr =3D curr_thr; - else - { - signalled_thr =3D iterate_over_threads (find_signalled_thread, NULL)= ; - if (signalled_thr =3D=3D NULL) -=09signalled_thr =3D curr_thr; - } + "First thread" is what tools use to infer the signalled + thread. */ + thread_info *signalled_thr =3D find_signalled_thread (); =20 thread_args.gdbarch =3D gdbarch; thread_args.obfd =3D obfd; thread_args.note_data =3D note_data; thread_args.note_size =3D note_size; - thread_args.stop_signal =3D signalled_thr->suspend.stop_signal; + if (signalled_thr !=3D nullptr) + thread_args.stop_signal =3D signalled_thr->suspend.stop_signal; + else + thread_args.stop_signal =3D GDB_SIGNAL_0; =20 - linux_corefile_thread (signalled_thr, &thread_args); + if (signalled_thr !=3D nullptr) + linux_corefile_thread (signalled_thr, &thread_args); for (thread_info *thr : current_inferior ()->non_exited_threads ()) { if (thr =3D=3D signalled_thr) --=20 2.14.5