public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: Simon Marchi <simark@simark.ca>,
	Simon Marchi <simon.marchi@efficios.com>,
	gdb-patches@sourceware.org
Subject: Re: [PATCH] gdb: fix dealloc function not being called for frame 0
Date: Wed, 15 Feb 2023 10:39:59 +0100	[thread overview]
Message-ID: <8b8d6d16-ed28-bebb-9136-85fc81968fa5@suse.de> (raw)
In-Reply-To: <30ee85a3-d6aa-c69e-2fe6-3c6d53a11a90@simark.ca>

[-- Attachment #1: Type: text/plain, Size: 4984 bytes --]

On 2/10/23 04:10, Simon Marchi wrote:
> 
>> @@ -2105,7 +2106,23 @@ reinit_frame_cache (void)
>>     invalidate_selected_frame ();
>>   
>>     /* Invalidate cache.  */
>> -  sentinel_frame = NULL;
>> +  if (sentinel_frame != nullptr)
>> +    {
>> +      /* If frame 0's id is not computed, it is not in the frame stash, so its
>> +	 dealloc functions will not be called when emptying the frash stash.
>> +	 Call frame_info_del manually in that case.  */
>> +      frame_info *current_frame = sentinel_frame->prev;
>> +      if (current_frame != nullptr)
>> +	{
>> +	  gdb_assert (current_frame->this_id.p != frame_id_status::COMPUTING);
> 
> Well, this gdb_assert happens to cause a failure in
> gdb.server/server-kill.exp:
> 
>      (gdb) PASS: gdb.server/server-kill.exp: kill_pid_of=inferior: test_unwind_syms: p server_pid
>      Executing on target: kill -9 1567851    (timeout = 300)
>      builtin_spawn -ignore SIGHUP kill -9 1567851
>      bt
>      /home/simark/src/binutils-gdb/gdb/frame.c:2117: internal-error: reinit_frame_cache: Assertion `current_frame->this_id.p != frame_id_status::COMPUTING' failed.
>      A problem internal to GDB has been detected, further debugging may prove unreliable.
>      FAIL: gdb.server/server-kill.exp: kill_pid_of=inferior: test_unwind_syms: bt (GDB internal error)
> 
> This happens because the remote connection breaks while computing a
> frame id.  The stack looks roughly like this (many frames removed for
> readability):
> 
> 0x55cd4623396c internal_error_loc(char const*, int, char const*, ...)
>          /home/simark/src/binutils-gdb/gdbsupport/errors.cc:58
> 0x55cd4434f5a1 reinit_frame_cache()
>          /home/simark/src/binutils-gdb/gdb/frame.c:2117
> 0x55cd457e1bce switch_to_no_thread()
>          /home/simark/src/binutils-gdb/gdb/thread.c:1330
> 0x55cd44618270 switch_to_inferior_no_thread(inferior*)
>          /home/simark/src/binutils-gdb/gdb/inferior.c:671
> 0x55cd451467c9 remote_unpush_target
>          /home/simark/src/binutils-gdb/gdb/remote.c:5903
> 0x55cd45183b88 unpush_and_perror
>          /home/simark/src/binutils-gdb/gdb/remote.c:9612
> 0x55cd451840ce remote_target::readchar(int)
>          /home/simark/src/binutils-gdb/gdb/remote.c:9652
> 0x55cd45188e91 remote_target::getpkt_or_notif_sane_1(std::__debug::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int, int, int*)
>          /home/simark/src/binutils-gdb/gdb/remote.c:10118
> 0x55cd4518a2fe remote_target::getpkt_sane(std::__debug::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int)
>          /home/simark/src/binutils-gdb/gdb/remote.c:10220
> 0x55cd451889d6 remote_target::getpkt(std::__debug::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int)
>          /home/simark/src/binutils-gdb/gdb/remote.c:10062
> 0x55cd45181137 remote_target::remote_read_bytes_1(unsigned long, unsigned char*, unsigned long, int, unsigned long*)
>          /home/simark/src/binutils-gdb/gdb/remote.c:9379
> 0x55cd45182772 remote_target::remote_read_bytes(unsigned long, unsigned char*, unsigned long, int, unsigned long*)
>          /home/simark/src/binutils-gdb/gdb/remote.c:9503
> 0x55cd4519cd2d remote_target::xfer_partial(target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*)
>          /home/simark/src/binutils-gdb/gdb/remote.c:11421
> ...
> 0x55cd4433d812 compute_frame_id
>          /home/simark/src/binutils-gdb/gdb/frame.c:606
> 
> So, I will remove that gdb_assert and simplify the code to:
> 
>        /* If frame 0's id is not computed, it is not in the frame stash, so its
> 	 dealloc functions will not be called when emptying the frash stash.
> 	 Call frame_info_del manually in that case.  */
>        frame_info *current_frame = sentinel_frame->prev;
>        if (current_frame != nullptr
> 	  && current_frame->this_id.p == frame_id_status::NOT_COMPUTED)
> 	frame_info_del (current_frame);
> 
> With that change, the test passes again.
> 
> If the state of the id of the current frame is "COMPUTING", I think it's
> better not to call frame_info_del and the dealloc functions, because the
> state of the per-unwinder cache object is maybe not in a state expected
> that the dealloc functions expect.  If something goes wrong during the
> computation of the frame id, I think it's best to let the unwinder make
> sure to clean up anything it has started.

Hi Simon,

I've:
- applied the initial patch
- verified that it fixes the gdb.btrace/record_goto.exp test-case
- verified that it breaks the gdb.server/server-kill.exp test-case
- applied your proposed change (attached in patch form for clarity)
- verified that it fixes the gdb.server/server-kill.exp test-case
- verified that it still fixes the gdb.btrace/record_goto.exp test-case
- done a complete build and test run, no issues found (in other words,
   I'm back to just one FAIL, in gdb.server/monitor-exit-quit.exp,
   PR29833)

Thanks,
- Tom

[-- Attachment #2: 0001-fixup.patch --]
[-- Type: text/x-patch, Size: 1073 bytes --]

From a63fe09438deba286464ac79685587890ea8ae39 Mon Sep 17 00:00:00 2001
From: Simon Marchi <simon.marchi@efficios.com>
Date: Wed, 15 Feb 2023 09:43:35 +0100
Subject: [PATCH] fixup

---
 gdb/frame.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/gdb/frame.c b/gdb/frame.c
index 69730979703..6629f444afe 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2112,13 +2112,9 @@ reinit_frame_cache (void)
 	 dealloc functions will not be called when emptying the frash stash.
 	 Call frame_info_del manually in that case.  */
       frame_info *current_frame = sentinel_frame->prev;
-      if (current_frame != nullptr)
-	{
-	  gdb_assert (current_frame->this_id.p != frame_id_status::COMPUTING);
-
-	  if (current_frame->this_id.p == frame_id_status::NOT_COMPUTED)
-	    frame_info_del (current_frame);
-	}
+      if (current_frame != nullptr
+	  && current_frame->this_id.p == frame_id_status::NOT_COMPUTED)
+	frame_info_del (current_frame);
 
       sentinel_frame = nullptr;
     }

base-commit: b6daa77d0d91216266bccbe182cc7dc689591692
-- 
2.35.3


  reply	other threads:[~2023-02-15  9:39 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-09 19:50 Simon Marchi
2023-02-10  3:10 ` Simon Marchi
2023-02-15  9:39   ` Tom de Vries [this message]
2023-02-15 16:42     ` Simon Marchi
2023-02-15 17:56       ` Tom de Vries
2023-02-15 18:01 ` Tom de Vries
2023-02-15 18:45   ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8b8d6d16-ed28-bebb-9136-85fc81968fa5@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    --cc=simark@simark.ca \
    --cc=simon.marchi@efficios.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).