[0/7] GDB busy loop when interrupting non-stop program (PR 26199)

Message ID 20200706190252.22552-1-pedro@palves.net
Headers show
Series
  • GDB busy loop when interrupting non-stop program (PR 26199)
Related show

Message

Pedro Alves July 6, 2020, 7:02 p.m.
This patch series fixes PR 26199, a GDB 10 blocker.

I discussed how to fix this with Simon, and we came to the conclusion
that we can fix it by removing code.  Easy.  :-) That's the last patch
in the series.

Well, not so easy, actually... :-/

Doing that alone caused gdb.multi/multi-target.exp to regress.  And
the reason was that the fix for PR 261299 made that testcase trip on a
few latent bugs...  One of those bugs also caused a similar 100% cpu
busy loop.

And then, while fixing those, I added a new test scenario to
gdb.multi/multi-target.exp to exercise the TARGET_WAITKIND_NO_RESUMED
handling fixes in this series.  That new test requires sending Ctrl-C
to GDB after the test is done with, in order to cleanly kill gdbserver
via "monitor exit".  But, that Ctrl-C didn't work, due to an issue
with GDB's terminal handling, GDB would just hang...

That's all fixed by this series.

Pedro Alves (6):
  Fix spurious unhandled remote %Stop notifications
  Fix latent bug in target_pass_ctrlc
  Avoid constant stream of TARGET_WAITKIND_NO_RESUMED
  Fix handle_no_resumed w/ multiple targets
  Make handle_no_resumed transfer terminal
  Testcase for previous handle_no_resumed fixes

Simon Marchi (1):
  Fix GDB busy loop when interrupting non-stop program (PR 26199)

 gdb/infrun.c                             | 116 +++++++++++++++++++++----------
 gdb/remote.c                             |  15 +++-
 gdb/target.c                             |   2 +-
 gdb/testsuite/gdb.multi/multi-target.c   |   4 +-
 gdb/testsuite/gdb.multi/multi-target.exp |  76 ++++++++++++++++++++
 5 files changed, 173 insertions(+), 40 deletions(-)


base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0
-- 
2.14.5

Comments

Simon Marchi July 6, 2020, 9:28 p.m. | #1
On 2020-07-06 3:02 p.m., Pedro Alves wrote:
> This patch series fixes PR 26199, a GDB 10 blocker.

> 

> I discussed how to fix this with Simon, and we came to the conclusion

> that we can fix it by removing code.  Easy.  :-) That's the last patch

> in the series.

> 

> Well, not so easy, actually... :-/

> 

> Doing that alone caused gdb.multi/multi-target.exp to regress.  And

> the reason was that the fix for PR 261299 made that testcase trip on a

> few latent bugs...  One of those bugs also caused a similar 100% cpu

> busy loop.

> 

> And then, while fixing those, I added a new test scenario to

> gdb.multi/multi-target.exp to exercise the TARGET_WAITKIND_NO_RESUMED

> handling fixes in this series.  That new test requires sending Ctrl-C

> to GDB after the test is done with, in order to cleanly kill gdbserver

> via "monitor exit".  But, that Ctrl-C didn't work, due to an issue

> with GDB's terminal handling, GDB would just hang...

> 

> That's all fixed by this series.

> 

> Pedro Alves (6):

>   Fix spurious unhandled remote %Stop notifications

>   Fix latent bug in target_pass_ctrlc

>   Avoid constant stream of TARGET_WAITKIND_NO_RESUMED

>   Fix handle_no_resumed w/ multiple targets

>   Make handle_no_resumed transfer terminal

>   Testcase for previous handle_no_resumed fixes

> 

> Simon Marchi (1):

>   Fix GDB busy loop when interrupting non-stop program (PR 26199)

> 

>  gdb/infrun.c                             | 116 +++++++++++++++++++++----------

>  gdb/remote.c                             |  15 +++-

>  gdb/target.c                             |   2 +-

>  gdb/testsuite/gdb.multi/multi-target.c   |   4 +-

>  gdb/testsuite/gdb.multi/multi-target.exp |  76 ++++++++++++++++++++

>  5 files changed, 173 insertions(+), 40 deletions(-)

> 

> 

> base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0

> -- 

> 2.14.5

> 


I am not sure why I didn't see this earlier, but gdb.multi/multi-target.exp
fails for me with my ASan-enabled build, using current master.  There is
a use after free.  Do you see the same?  I've attached the ASan log.

Simon
==18555==ERROR: AddressSanitizer: heap-use-after-free on address 0x621004670aa8 at pc 0x0000007ab125 bp 0x7ffdecaecd20 sp 0x7ffdecaecd10
READ of size 4 at 0x621004670aa8 thread T0
    #0 0x7ab124 in dwarf2_frame_this_id /home/smarchi/src/binutils-gdb/gdb/dwarf2/frame.c:1228
    #1 0x983ec5 in compute_frame_id /home/smarchi/src/binutils-gdb/gdb/frame.c:550
    #2 0x9841ee in get_frame_id(frame_info*) /home/smarchi/src/binutils-gdb/gdb/frame.c:582
    #3 0x1093faa in scoped_restore_current_thread::scoped_restore_current_thread() /home/smarchi/src/binutils-gdb/gdb/thread.c:1462
    #4 0xaee5ba in fetch_inferior_event(void*) /home/smarchi/src/binutils-gdb/gdb/infrun.c:3968
    #5 0xaa990b in inferior_event_handler(inferior_event_type, void*) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:43
    #6 0xea61b6 in remote_async_serial_handler /home/smarchi/src/binutils-gdb/gdb/remote.c:14161
    #7 0xefca8a in run_async_handler_and_reschedule /home/smarchi/src/binutils-gdb/gdb/ser-base.c:137
    #8 0xefcd23 in fd_event /home/smarchi/src/binutils-gdb/gdb/ser-base.c:188
    #9 0x15a7416 in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:548
    #10 0x15a7c36 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:673
    #11 0x15a5dbb in gdb_do_one_event() /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:215
    #12 0xbfe62d in start_event_loop /home/smarchi/src/binutils-gdb/gdb/main.c:356
    #13 0xbfe935 in captured_command_loop /home/smarchi/src/binutils-gdb/gdb/main.c:416
    #14 0xc01d39 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1253
    #15 0xc01dc9 in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1268
    #16 0x414ddd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
    #17 0x7f590110b82f in __libc_start_main ../csu/libc-start.c:291
    #18 0x414bd8 in _start (/home/smarchi/build/binutils-gdb/gdb/gdb+0x414bd8)

0x621004670aa8 is located 424 bytes inside of 4064-byte region [0x621004670900,0x6210046718e0)
freed by thread T0 here:
    #0 0x7f5903c42c7f in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bc7f)
    #1 0x98fb0c in xfree<void> /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/common-utils.h:62
    #2 0x160804b in call_freefun /home/smarchi/src/binutils-gdb/libiberty/obstack.c:103
    #3 0x1608a72 in _obstack_free /home/smarchi/src/binutils-gdb/libiberty/obstack.c:280
    #4 0x98af3b in reinit_frame_cache() /home/smarchi/src/binutils-gdb/gdb/frame.c:1864
    #5 0x109341c in switch_to_no_thread() /home/smarchi/src/binutils-gdb/gdb/thread.c:1301
    #6 0xad0cf2 in switch_to_inferior_no_thread(inferior*) /home/smarchi/src/binutils-gdb/gdb/inferior.c:612
    #7 0xe76c9f in remote_unpush_target /home/smarchi/src/binutils-gdb/gdb/remote.c:5521
    #8 0xe8d997 in remote_target::readchar(int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9138
    #9 0xe90082 in remote_target::getpkt_or_notif_sane_1(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int, int, int*) /home/smarchi/src/binutils-gdb/gdb/remote.c:9684
    #10 0xe90adc in remote_target::getpkt_sane(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9791
    #11 0xe8fe58 in remote_target::getpkt(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9624
    #12 0xe8c4b6 in remote_target::remote_read_bytes_1(unsigned long, unsigned char*, unsigned long, int, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:8861
    #13 0xe8cd1f in remote_target::remote_read_bytes(unsigned long, unsigned char*, unsigned long, int, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:8988
    #14 0xe96134 in remote_target::xfer_partial(target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:10988
    #15 0x104a76f in raw_memory_xfer_partial(target_ops*, unsigned char*, unsigned char const*, unsigned long, long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:918
    #16 0x104b65c in target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:1148
    #17 0x104c4b0 in target_read_partial /home/smarchi/src/binutils-gdb/gdb/target.c:1379
    #18 0x104c68e in target_read(target_ops*, target_object, char const*, unsigned char*, unsigned long, long) /home/smarchi/src/binutils-gdb/gdb/target.c:1419
    #19 0x104bd7a in target_read_raw_memory(unsigned long, unsigned char*, long) /home/smarchi/src/binutils-gdb/gdb/target.c:1252
    #20 0x761b32 in dcache_read_line /home/smarchi/src/binutils-gdb/gdb/dcache.c:336
    #21 0x761ebf in dcache_peek_byte /home/smarchi/src/binutils-gdb/gdb/dcache.c:403
    #22 0x76244d in dcache_read_memory_partial(target_ops*, dcache_struct*, unsigned long, unsigned char*, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/dcache.c:484
    #23 0x104ae00 in memory_xfer_partial_1 /home/smarchi/src/binutils-gdb/gdb/target.c:1033
    #24 0x104b03d in memory_xfer_partial /home/smarchi/src/binutils-gdb/gdb/target.c:1076
    #25 0x104b5c7 in target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:1133
    #26 0x11e85c3 in read_value_memory(value*, long, int, unsigned long, unsigned char*, unsigned long) /home/smarchi/src/binutils-gdb/gdb/valops.c:956
    #27 0x121eb88 in value_fetch_lazy_memory /home/smarchi/src/binutils-gdb/gdb/value.c:3764
    #28 0x121fa89 in value_fetch_lazy(value*) /home/smarchi/src/binutils-gdb/gdb/value.c:3910
    #29 0x1214bcc in value_optimized_out(value*) /home/smarchi/src/binutils-gdb/gdb/value.c:1411

previously allocated by thread T0 here:
    #0 0x7f5903c43078 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c078)
    #1 0x4a1c73 in xmalloc /home/smarchi/src/binutils-gdb/gdb/alloc.c:60
    #2 0x1607f59 in call_chunkfun /home/smarchi/src/binutils-gdb/libiberty/obstack.c:94
    #3 0x1608104 in _obstack_begin_worker /home/smarchi/src/binutils-gdb/libiberty/obstack.c:141
    #4 0x16083b7 in _obstack_begin /home/smarchi/src/binutils-gdb/libiberty/obstack.c:164
    #5 0x98af5a in reinit_frame_cache() /home/smarchi/src/binutils-gdb/gdb/frame.c:1865
    #6 0x109348a in switch_to_thread(thread_info*) /home/smarchi/src/binutils-gdb/gdb/thread.c:1316
    #7 0xad0ed4 in inferior_command /home/smarchi/src/binutils-gdb/gdb/inferior.c:636
    #8 0x6524e3 in do_const_cfunc /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
    #9 0x65ae7c in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2187
    #10 0x10a85fd in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:668
    #11 0x94bb32 in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:588
    #12 0x94c436 in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /home/smarchi/src/binutils-gdb/gdb/event-top.c:773
    #13 0x94a716 in gdb_rl_callback_handler /home/smarchi/src/binutils-gdb/gdb/event-top.c:219
    #14 0x12afe46 in rl_callback_read_char /home/smarchi/src/binutils-gdb/readline/readline/callback.c:281
    #15 0x94a28a in gdb_rl_callback_read_char_wrapper_noexcept /home/smarchi/src/binutils-gdb/gdb/event-top.c:177
    #16 0x94a488 in gdb_rl_callback_read_char_wrapper /home/smarchi/src/binutils-gdb/gdb/event-top.c:194
    #17 0x94b6e1 in stdin_event_handler(int, void*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:516
    #18 0x15a7416 in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:548
    #19 0x15a7c36 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:673
    #20 0x15a5dbb in gdb_do_one_event() /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:215
    #21 0xbfe62d in start_event_loop /home/smarchi/src/binutils-gdb/gdb/main.c:356
    #22 0xbfe935 in captured_command_loop /home/smarchi/src/binutils-gdb/gdb/main.c:416
    #23 0xc01d39 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1253
    #24 0xc01dc9 in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1268
    #25 0x414ddd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
    #26 0x7f590110b82f in __libc_start_main ../csu/libc-start.c:291
Pedro Alves July 7, 2020, 12:25 a.m. | #2
On 7/6/20 10:28 PM, Simon Marchi wrote:
> On 2020-07-06 3:02 p.m., Pedro Alves wrote:

>> This patch series fixes PR 26199, a GDB 10 blocker.

>>

>> I discussed how to fix this with Simon, and we came to the conclusion

>> that we can fix it by removing code.  Easy.  :-) That's the last patch

>> in the series.

>>

>> Well, not so easy, actually... :-/

>>

>> Doing that alone caused gdb.multi/multi-target.exp to regress.  And

>> the reason was that the fix for PR 261299 made that testcase trip on a

>> few latent bugs...  One of those bugs also caused a similar 100% cpu

>> busy loop.

>>

>> And then, while fixing those, I added a new test scenario to

>> gdb.multi/multi-target.exp to exercise the TARGET_WAITKIND_NO_RESUMED

>> handling fixes in this series.  That new test requires sending Ctrl-C

>> to GDB after the test is done with, in order to cleanly kill gdbserver

>> via "monitor exit".  But, that Ctrl-C didn't work, due to an issue

>> with GDB's terminal handling, GDB would just hang...

>>

>> That's all fixed by this series.

>>

>> Pedro Alves (6):

>>   Fix spurious unhandled remote %Stop notifications

>>   Fix latent bug in target_pass_ctrlc

>>   Avoid constant stream of TARGET_WAITKIND_NO_RESUMED

>>   Fix handle_no_resumed w/ multiple targets

>>   Make handle_no_resumed transfer terminal

>>   Testcase for previous handle_no_resumed fixes

>>

>> Simon Marchi (1):

>>   Fix GDB busy loop when interrupting non-stop program (PR 26199)

>>

>>  gdb/infrun.c                             | 116 +++++++++++++++++++++----------

>>  gdb/remote.c                             |  15 +++-

>>  gdb/target.c                             |   2 +-

>>  gdb/testsuite/gdb.multi/multi-target.c   |   4 +-

>>  gdb/testsuite/gdb.multi/multi-target.exp |  76 ++++++++++++++++++++

>>  5 files changed, 173 insertions(+), 40 deletions(-)

>>

>>

>> base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0

>> -- 

>> 2.14.5

>>

> I am not sure why I didn't see this earlier, but gdb.multi/multi-target.exp

> fails for me with my ASan-enabled build, using current master.  There is

> a use after free.  Do you see the same?  I've attached the ASan log.


I can reproduce it.

This is triggering right after GDB sends "monitor exit" to
tear down gdbserver.  If GDBserver is fast enough to exit and
close its end of the socket, then gdb may end up trying to
send a packet to gdbserver, which makes gdb realize the socket
is closed, close the remote target, and throw an exception.

I'm attaching a patch one can use to reproduce this more
easily.  Once gdb_interact kicks, you can attach to
gdb from another terminal, and then issue "monitor exit"
from the inferior gdb.

> 

> ==18555==ERROR: AddressSanitizer: heap-use-after-free on address 0x621004670aa8 at pc 0x0000007ab125 bp 0x7ffdecaecd20 sp 0x7ffdecaecd10

> READ of size 4 at 0x621004670aa8 thread T0

>     #0 0x7ab124 in dwarf2_frame_this_id /home/smarchi/src/binutils-gdb/gdb/dwarf2/frame.c:1228

>     #1 0x983ec5 in compute_frame_id /home/smarchi/src/binutils-gdb/gdb/frame.c:550

>     #2 0x9841ee in get_frame_id(frame_info*) /home/smarchi/src/binutils-gdb/gdb/frame.c:582

>     #3 0x1093faa in scoped_restore_current_thread::scoped_restore_current_thread() /home/smarchi/src/binutils-gdb/gdb/thread.c:1462

>     #4 0xaee5ba in fetch_inferior_event(void*) /home/smarchi/src/binutils-gdb/gdb/infrun.c:3968

>     #5 0xaa990b in inferior_event_handler(inferior_event_type, void*) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:43

>     #6 0xea61b6 in remote_async_serial_handler /home/smarchi/src/binutils-gdb/gdb/remote.c:14161

>     #7 0xefca8a in run_async_handler_and_reschedule /home/smarchi/src/binutils-gdb/gdb/ser-base.c:137

>     #8 0xefcd23 in fd_event /home/smarchi/src/binutils-gdb/gdb/ser-base.c:188

>     #9 0x15a7416 in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:548

>     #10 0x15a7c36 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:673

>     #11 0x15a5dbb in gdb_do_one_event() /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:215

>     #12 0xbfe62d in start_event_loop /home/smarchi/src/binutils-gdb/gdb/main.c:356

>     #13 0xbfe935 in captured_command_loop /home/smarchi/src/binutils-gdb/gdb/main.c:416

>     #14 0xc01d39 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1253

>     #15 0xc01dc9 in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1268

>     #16 0x414ddd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32

>     #17 0x7f590110b82f in __libc_start_main ../csu/libc-start.c:291

>     #18 0x414bd8 in _start (/home/smarchi/build/binutils-gdb/gdb/gdb+0x414bd8)


So what happens is that above, we're in dwarf2_frame_this_id, just after the dwarf2_frame_cache
call.  So you would think that the "cache" variable would be good.  But it's not, that's
what has been freed.  But why has it been freed?  See below.

> 

> 0x621004670aa8 is located 424 bytes inside of 4064-byte region [0x621004670900,0x6210046718e0)

> freed by thread T0 here:

>     #0 0x7f5903c42c7f in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bc7f)

>     #1 0x98fb0c in xfree<void> /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/common-utils.h:62

>     #2 0x160804b in call_freefun /home/smarchi/src/binutils-gdb/libiberty/obstack.c:103

>     #3 0x1608a72 in _obstack_free /home/smarchi/src/binutils-gdb/libiberty/obstack.c:280

>     #4 0x98af3b in reinit_frame_cache() /home/smarchi/src/binutils-gdb/gdb/frame.c:1864

>     #5 0x109341c in switch_to_no_thread() /home/smarchi/src/binutils-gdb/gdb/thread.c:1301

>     #6 0xad0cf2 in switch_to_inferior_no_thread(inferior*) /home/smarchi/src/binutils-gdb/gdb/inferior.c:612

>     #7 0xe76c9f in remote_unpush_target /home/smarchi/src/binutils-gdb/gdb/remote.c:5521

>     #8 0xe8d997 in remote_target::readchar(int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9138

>     #9 0xe90082 in remote_target::getpkt_or_notif_sane_1(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int, int, int*) /home/smarchi/src/binutils-gdb/gdb/remote.c:9684

>     #10 0xe90adc in remote_target::getpkt_sane(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9791

>     #11 0xe8fe58 in remote_target::getpkt(std::vector<char, gdb::default_init_allocator<char, std::allocator<char> > >*, int) /home/smarchi/src/binutils-gdb/gdb/remote.c:9624

>     #12 0xe8c4b6 in remote_target::remote_read_bytes_1(unsigned long, unsigned char*, unsigned long, int, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:8861

>     #13 0xe8cd1f in remote_target::remote_read_bytes(unsigned long, unsigned char*, unsigned long, int, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:8988

>     #14 0xe96134 in remote_target::xfer_partial(target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/remote.c:10988

>     #15 0x104a76f in raw_memory_xfer_partial(target_ops*, unsigned char*, unsigned char const*, unsigned long, long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:918

>     #16 0x104b65c in target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:1148

>     #17 0x104c4b0 in target_read_partial /home/smarchi/src/binutils-gdb/gdb/target.c:1379

>     #18 0x104c68e in target_read(target_ops*, target_object, char const*, unsigned char*, unsigned long, long) /home/smarchi/src/binutils-gdb/gdb/target.c:1419

>     #19 0x104bd7a in target_read_raw_memory(unsigned long, unsigned char*, long) /home/smarchi/src/binutils-gdb/gdb/target.c:1252

>     #20 0x761b32 in dcache_read_line /home/smarchi/src/binutils-gdb/gdb/dcache.c:336

>     #21 0x761ebf in dcache_peek_byte /home/smarchi/src/binutils-gdb/gdb/dcache.c:403

>     #22 0x76244d in dcache_read_memory_partial(target_ops*, dcache_struct*, unsigned long, unsigned char*, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/dcache.c:484

>     #23 0x104ae00 in memory_xfer_partial_1 /home/smarchi/src/binutils-gdb/gdb/target.c:1033

>     #24 0x104b03d in memory_xfer_partial /home/smarchi/src/binutils-gdb/gdb/target.c:1076

>     #25 0x104b5c7 in target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) /home/smarchi/src/binutils-gdb/gdb/target.c:1133

>     #26 0x11e85c3 in read_value_memory(value*, long, int, unsigned long, unsigned char*, unsigned long) /home/smarchi/src/binutils-gdb/gdb/valops.c:956

>     #27 0x121eb88 in value_fetch_lazy_memory /home/smarchi/src/binutils-gdb/gdb/value.c:3764

>     #28 0x121fa89 in value_fetch_lazy(value*) /home/smarchi/src/binutils-gdb/gdb/value.c:3910

>     #29 0x1214bcc in value_optimized_out(value*) /home/smarchi/src/binutils-gdb/gdb/value.c:1411


It is not immediately obvious because the backtrace is trimmed, but this backtrace that lead
to the free is _within_ the dwarf2_frame_this_id -> dwarf2_frame_cache:

(top-gdb) bt 
#0  reinit_frame_cache () at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/frame.c:1855
#1  0x00000000014ff7b0 in switch_to_no_thread () at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:1301
#2  0x0000000000f66d3e in switch_to_inferior_no_thread (inf=0x615000338180) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inferior.c:626
#3  0x00000000012f3826 in remote_unpush_target (target=0x6170000c5900) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:5521
#4  0x00000000013097e0 in remote_target::readchar (this=0x6170000c5900, timeout=2) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9137
#5  0x000000000130be4d in remote_target::getpkt_or_notif_sane_1 (this=0x6170000c5900, buf=0x6170000c5918, forever=0, expecting_notif=0, is_notif=0x0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9683
#6  0x000000000130c8ab in remote_target::getpkt_sane (this=0x6170000c5900, buf=0x6170000c5918, forever=0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9790
#7  0x000000000130bc0d in remote_target::getpkt (this=0x6170000c5900, buf=0x6170000c5918, forever=0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9623
#8  0x000000000130838e in remote_target::remote_read_bytes_1 (this=0x6170000c5900, memaddr=0x7fffffffcdc0, myaddr=0x6080000ad3bc "", len_units=64, unit_size=1, xfered_len_units=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:8860
#9  0x0000000001308bd2 in remote_target::remote_read_bytes (this=0x6170000c5900, memaddr=0x7fffffffcdc0, myaddr=0x6080000ad3bc "", len=64, unit_size=1, xfered_len=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:8987
#10 0x0000000001311ed1 in remote_target::xfer_partial (this=0x6170000c5900, object=TARGET_OBJECT_MEMORY, annex=0x0, readbuf=0x6080000ad3bc "", writebuf=0x0, offset=140737488342464, len=64, xfered_len=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:10988
#11 0x00000000014ba969 in raw_memory_xfer_partial (ops=0x6170000c5900, readbuf=0x6080000ad3bc "", writebuf=0x0, memaddr=140737488342464, len=64, xfered_len=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:918
#12 0x00000000014bb720 in target_xfer_partial (ops=0x6170000c5900, object=TARGET_OBJECT_RAW_MEMORY, annex=0x0, readbuf=0x6080000ad3bc "", writebuf=0x0, offset=140737488342464, len=64, xfered_len=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1148
#13 0x00000000014bc3b5 in target_read_partial (ops=0x6170000c5900, object=TARGET_OBJECT_RAW_MEMORY, annex=0x0, buf=0x6080000ad3bc "", offset=140737488342464, len=64, xfered_len=0x7fff6a29b9a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1380
#14 0x00000000014bc593 in target_read (ops=0x6170000c5900, object=TARGET_OBJECT_RAW_MEMORY, annex=0x0, buf=0x6080000ad3bc "", offset=140737488342464, len=64) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1419
#15 0x00000000014bbd4d in target_read_raw_memory (memaddr=0x7fffffffcdc0, myaddr=0x6080000ad3bc "", len=64) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1252
#16 0x0000000000bf27df in dcache_read_line (dcache=0x6060001eddc0, db=0x6080000ad3a0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dcache.c:336
#17 0x0000000000bf2b72 in dcache_peek_byte (dcache=0x6060001eddc0, addr=0x7fffffffcdd8, ptr=0x6020001231b0 "") at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dcache.c:403
#18 0x0000000000bf3103 in dcache_read_memory_partial (ops=0x6170000c5900, dcache=0x6060001eddc0, memaddr=0x7fffffffcdd8, myaddr=0x6020001231b0 "", len=8, xfered_len=0x7fff6a29bf20) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dcache.c:484
#19 0x00000000014bafe9 in memory_xfer_partial_1 (ops=0x6170000c5900, object=TARGET_OBJECT_STACK_MEMORY, readbuf=0x6020001231b0 "", writebuf=0x0, memaddr=140737488342488, len=8, xfered_len=0x7fff6a29bf20) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1034
#20 0x00000000014bb212 in memory_xfer_partial (ops=0x6170000c5900, object=TARGET_OBJECT_STACK_MEMORY, readbuf=0x6020001231b0 "", writebuf=0x0, memaddr=140737488342488, len=8, xfered_len=0x7fff6a29bf20) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1076
#21 0x00000000014bb6b3 in target_xfer_partial (ops=0x6170000c5900, object=TARGET_OBJECT_STACK_MEMORY, annex=0x0, readbuf=0x6020001231b0 "", writebuf=0x0, offset=140737488342488, len=8, xfered_len=0x7fff6a29bf20) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:1133
#22 0x000000000164564d in read_value_memory (val=0x60f000029440, bit_offset=0, stack=1, memaddr=0x7fffffffcdd8, buffer=0x6020001231b0 "", length=8) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/valops.c:956
#23 0x0000000001680fff in value_fetch_lazy_memory (val=0x60f000029440) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/value.c:3764
#24 0x0000000001681efd in value_fetch_lazy (val=0x60f000029440) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/value.c:3910
#25 0x0000000001676143 in value_optimized_out (value=0x60f000029440) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/value.c:1411
#26 0x0000000000e0fcb8 in frame_register_unwind (next_frame=0x6210066bfde0, regnum=16, optimizedp=0x7fff6a29c200, unavailablep=0x7fff6a29c240, lvalp=0x7fff6a29c2c0, addrp=0x7fff6a29c300, realnump=0x7fff6a29c280, bufferp=0x7fff6a29c3a0 "@\304)j\377\177") at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/frame.c:1144
#27 0x0000000000e10418 in frame_unwind_register (next_frame=0x6210066bfde0, regnum=16, buf=0x7fff6a29c3a0 "@\304)j\377\177") at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/frame.c:1196
#28 0x0000000000f00431 in i386_unwind_pc (gdbarch=0x6210043d0110, next_frame=0x6210066bfde0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/i386-tdep.c:1969
#29 0x0000000000e39724 in gdbarch_unwind_pc (gdbarch=0x6210043d0110, next_frame=0x6210066bfde0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/gdbarch.c:3056
#30 0x0000000000c2ea90 in dwarf2_tailcall_sniffer_first (this_frame=0x6210066bfde0, tailcall_cachep=0x6210066bfee0, entry_cfa_sp_offsetp=0x0) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dwarf2/frame-tailcall.c:423
#31 0x0000000000c36bdb in dwarf2_frame_cache (this_frame=0x6210066bfde0, this_cache=0x6210066bfdf8) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dwarf2/frame.c:1198
#32 0x0000000000c36eb3 in dwarf2_frame_this_id (this_frame=0x6210066bfde0, this_cache=0x6210066bfdf8, this_id=0x6210066bfe40) at /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/dwarf2/frame.c:1226

Note that remote_target::readchar in frame #3 throws TARGET_CLOSE_ERROR after
that remote_unpush_target in frame #3 returns.

The problem is that that TARGET_CLOSE_ERROR is swallowed by value_optimized_out
in frame #25.

If we fix that one, then we run into dwarf2_tailcall_sniffer_first swallowing
the exception in frame #30 too.

The attached patch fixes that issue for me, but I've not
run the whole testsuite with it yet.  I'm not 100% sure that that
makes us catch all the important exceptions.  I've thought before
about making TARGET_CLOSE_ERROR be more like a QUIT exception, which
is not caught by catch gdb_exception_error, but I've resisted exactly
because it tends to be wrong to swallow too much, I think.

However, with the fix, the testcase now runs into another Asan-reported issue:

=================================================================
==9211==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000b1080 at pc 0x000000dd0344 bp 0x7ffe4bebca90 sp 0x7ffe4bebca80
READ of size 4 at 0x6160000b1080 thread T0
    #0 0xdd0343 in refcounted_object::incref() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/../gdbsupport/refcounted-object.h:34
    #1 0x150066f in scoped_restore_current_thread::scoped_restore_current_thread() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:1471
    #2 0xf83564 in fetch_inferior_event() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/infrun.c:3952
    #3 0xf40736 in inferior_event_handler(inferior_event_type) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inf-loop.c:42
    #4 0x1321e75 in remote_async_serial_handler /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:14160
    #5 0x1371849 in run_async_handler_and_reschedule /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/ser-base.c:137
    #6 0x1371ae2 in fd_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/ser-base.c:188
    #7 0x19fc1f7 in handle_file_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:548
    #8 0x19fca14 in gdb_wait_for_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:673
    #9 0x19fab94 in gdb_do_one_event() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:215
    #10 0x1087704 in start_event_loop /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:356
    #11 0x10879f5 in captured_command_loop /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:416
    #12 0x108aef1 in captured_main /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:1253
    #13 0x108af81 in gdb_main(captured_main_args*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:1268
    #14 0x8af9fa in main /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/gdb.c:32
    #15 0x7f07d5efbfe9 in __libc_start_main (/lib64/libc.so.6+0x20fe9)
    #16 0x8af809 in _start (/home/pedro/brno/pedro/gdb/binutils-gdb-2/build-asan/gdb/gdb+0x8af809)

0x6160000b1080 is located 0 bytes inside of 592-byte region [0x6160000b1080,0x6160000b12d0)
freed by thread T0 here:
    #0 0x7f07d97966d8 in operator delete(void*, unsigned long) (/lib64/libasan.so.4+0xe16d8)
    #1 0x14f7147 in delete_thread_1 /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:452
    #2 0x14f7171 in delete_thread(thread_info*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:460
    #3 0xf6278d in exit_inferior_1 /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inferior.c:204
    #4 0xf62b5b in exit_inferior(inferior*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inferior.c:236
    #5 0x14c32a6 in generic_mourn_inferior() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:3119
    #6 0x12f388a in remote_unpush_target /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:5523
    #7 0x1309835 in remote_target::readchar(int) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9137


Odd, kind of looks like we're mishandling the thread_info refcounts.
From 70b049caa3cf74f5ada6eeaa494caca09247479c Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>

Date: Mon, 6 Jul 2020 23:07:40 +0100
Subject: [PATCH] Crash reproducer

---
 gdb/remote.c                             | 2 ++
 gdb/testsuite/gdb.multi/multi-target.exp | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/gdb/remote.c b/gdb/remote.c
index 59075cb09f..79f5430bb0 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11281,6 +11281,8 @@ remote_target::rcmd (const char *command, struct ui_file *outbuf)
   if (putpkt (rs->buf) < 0)
     error (_("Communication problem with target."));
 
+  error ("boo");
+
   /* get/display the response */
   while (1)
     {
diff --git a/gdb/testsuite/gdb.multi/multi-target.exp b/gdb/testsuite/gdb.multi/multi-target.exp
index d19cee6595..d1d7b9a57e 100644
--- a/gdb/testsuite/gdb.multi/multi-target.exp
+++ b/gdb/testsuite/gdb.multi/multi-target.exp
@@ -111,6 +111,7 @@ proc cleanup_gdbservers { } {
     foreach { inferior_id spawn_id } $server_spawn_ids {
 	set server_spawn_id $spawn_id
 	gdb_test "inferior $inferior_id"
+	gdb_interact
 	gdbserver_exit 0
     }
     set server_spawn_ids [list]
@@ -520,6 +521,7 @@ with_test_prefix "continue" {
 	test_continue ${non-stop}
     }
 }
+return
 
 # Some basic all-stop Ctrl-C tests.
 with_test_prefix "interrupt" {

base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0
prerequisite-patch-id: 32ffdda7d7d774bc4df88bf848bcb796559b53ce
prerequisite-patch-id: 02021b74355b70debd344a6e445285c67dfef7d6
prerequisite-patch-id: c87fcf5a54f6805967cbf8ab107606c57d9ecf52
prerequisite-patch-id: ac7dee583d0ffa519c9d1cd89d27664bca68d8c1
prerequisite-patch-id: eac59ae2ea85d2d51e5be1b03e88a5641cc12c22
prerequisite-patch-id: 13da42ad04dc8e2e3bd6a556a0be0e17cf23669b
prerequisite-patch-id: fd3f09fdb58ddc1c595ea014716851f4c8fca48c
prerequisite-patch-id: 55b398673bd7edefb85d383c82785b668588e9c2
-- 
2.14.5
From fa0b349ab8fec78e3296fdd8042001cc54511032 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>

Date: Tue, 7 Jul 2020 01:19:55 +0100
Subject: [PATCH] Fix crash, part 1

---
 gdb/dwarf2/frame-tailcall.c | 6 ++++--
 gdb/value.c                 | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/gdb/dwarf2/frame-tailcall.c b/gdb/dwarf2/frame-tailcall.c
index 16dba2b201..cb9fd4a506 100644
--- a/gdb/dwarf2/frame-tailcall.c
+++ b/gdb/dwarf2/frame-tailcall.c
@@ -377,7 +377,7 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
      get_frame_address_in_block will decrease it by 1 in such case.  */
   this_pc = get_frame_address_in_block (this_frame);
 
-  /* Catch any unwinding errors.  */
+  /* Catch NO_ENTRY_VALUE_ERROR thrown by call_site_find_chain.  */
   try
     {
       int sp_regnum;
@@ -439,7 +439,9 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
     {
       if (entry_values_debug)
 	exception_print (gdb_stdout, except);
-      return;
+      if (except.error == NO_ENTRY_VALUE_ERROR)
+	return;
+      throw;
     }
 
   /* Ambiguous unwind or unambiguous unwind verified as matching.  */
diff --git a/gdb/value.c b/gdb/value.c
index 97a099ddbd..e22ef96c4c 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1413,6 +1413,8 @@ value_optimized_out (struct value *value)
       catch (const gdb_exception_error &ex)
 	{
 	  /* Fall back to checking value->optimized_out.  */
+	  if (ex.error != OPTIMIZED_OUT_ERROR)
+	    throw;
 	}
     }
 

base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0
prerequisite-patch-id: 32ffdda7d7d774bc4df88bf848bcb796559b53ce
prerequisite-patch-id: 02021b74355b70debd344a6e445285c67dfef7d6
prerequisite-patch-id: c87fcf5a54f6805967cbf8ab107606c57d9ecf52
prerequisite-patch-id: ac7dee583d0ffa519c9d1cd89d27664bca68d8c1
prerequisite-patch-id: eac59ae2ea85d2d51e5be1b03e88a5641cc12c22
prerequisite-patch-id: 13da42ad04dc8e2e3bd6a556a0be0e17cf23669b
prerequisite-patch-id: fd3f09fdb58ddc1c595ea014716851f4c8fca48c
-- 
2.14.5
Pedro Alves July 7, 2020, 1:27 a.m. | #3
On 7/7/20 1:25 AM, Pedro Alves wrote:

> However, with the fix, the testcase now runs into another Asan-reported issue:

> 

> =================================================================

> ==9211==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000b1080 at pc 0x000000dd0344 bp 0x7ffe4bebca90 sp 0x7ffe4bebca80

> READ of size 4 at 0x6160000b1080 thread T0

>     #0 0xdd0343 in refcounted_object::incref() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/../gdbsupport/refcounted-object.h:34

>     #1 0x150066f in scoped_restore_current_thread::scoped_restore_current_thread() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:1471

>     #2 0xf83564 in fetch_inferior_event() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/infrun.c:3952

>     #3 0xf40736 in inferior_event_handler(inferior_event_type) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inf-loop.c:42

>     #4 0x1321e75 in remote_async_serial_handler /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:14160

>     #5 0x1371849 in run_async_handler_and_reschedule /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/ser-base.c:137

>     #6 0x1371ae2 in fd_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/ser-base.c:188

>     #7 0x19fc1f7 in handle_file_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:548

>     #8 0x19fca14 in gdb_wait_for_event /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:673

>     #9 0x19fab94 in gdb_do_one_event() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdbsupport/event-loop.cc:215

>     #10 0x1087704 in start_event_loop /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:356

>     #11 0x10879f5 in captured_command_loop /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:416

>     #12 0x108aef1 in captured_main /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:1253

>     #13 0x108af81 in gdb_main(captured_main_args*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/main.c:1268

>     #14 0x8af9fa in main /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/gdb.c:32

>     #15 0x7f07d5efbfe9 in __libc_start_main (/lib64/libc.so.6+0x20fe9)

>     #16 0x8af809 in _start (/home/pedro/brno/pedro/gdb/binutils-gdb-2/build-asan/gdb/gdb+0x8af809)

> 

> 0x6160000b1080 is located 0 bytes inside of 592-byte region [0x6160000b1080,0x6160000b12d0)

> freed by thread T0 here:

>     #0 0x7f07d97966d8 in operator delete(void*, unsigned long) (/lib64/libasan.so.4+0xe16d8)

>     #1 0x14f7147 in delete_thread_1 /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:452

>     #2 0x14f7171 in delete_thread(thread_info*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/thread.c:460

>     #3 0xf6278d in exit_inferior_1 /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inferior.c:204

>     #4 0xf62b5b in exit_inferior(inferior*) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/inferior.c:236

>     #5 0x14c32a6 in generic_mourn_inferior() /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/target.c:3119

>     #6 0x12f388a in remote_unpush_target /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:5523

>     #7 0x1309835 in remote_target::readchar(int) /home/pedro/brno/pedro/gdb/binutils-gdb-2/build/../src/gdb/remote.c:9137

> 

> 

> Odd, kind of looks like we're mishandling the thread_info refcounts.

> 


This fixes it.  multi-target.exp now passes Asan-clean with this one on top
of "part 1" patch.  I still haven't run the full testsuite.

The issue is that the remote target is unpushed while within scoped_restore_current_thread' dtor's
get_frame_id call, which results in threads being deleted.  However, back in
scoped_restore_current_thread's ctor, we only increment the refcount after get_frame_id
returns.  Incrementing the refcounts earlier fixes it.

However, we should probably also propagate the TARGET_CLOSE_ERROR in this case.
That alone would fix it, though it seems cleaner to do both tweaks.
From 10203ffc8c57d92568b8e84b75389df25f3c4a58 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>

Date: Tue, 7 Jul 2020 01:50:10 +0100
Subject: [PATCH] Fix crash, part 2

---
 gdb/thread.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/gdb/thread.c b/gdb/thread.c
index f0722d3588..1ec047e35b 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1433,15 +1433,17 @@ scoped_restore_current_thread::~scoped_restore_current_thread ()
 
 scoped_restore_current_thread::scoped_restore_current_thread ()
 {
-  m_thread = NULL;
   m_inf = current_inferior ();
+  m_inf->incref ();
 
   if (inferior_ptid != null_ptid)
     {
-      thread_info *tp = inferior_thread ();
+      m_thread = inferior_thread ();
+      m_thread->incref ();
+
       struct frame_info *frame;
 
-      m_was_stopped = tp->state == THREAD_STOPPED;
+      m_was_stopped = m_thread->state == THREAD_STOPPED;
       if (m_was_stopped
 	  && target_has_registers
 	  && target_has_stack
@@ -1466,13 +1468,14 @@ scoped_restore_current_thread::scoped_restore_current_thread ()
 	{
 	  m_selected_frame_id = null_frame_id;
 	  m_selected_frame_level = -1;
-	}
 
-      tp->incref ();
-      m_thread = tp;
+	  /* Better let this propagate.  */
+	  if (ex.error == TARGET_CLOSE_ERROR)
+	    throw;
+	}
     }
-
-  m_inf->incref ();
+  else
+    m_thread = NULL;
 }
 
 /* See gdbthread.h.  */

base-commit: ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0
prerequisite-patch-id: 32ffdda7d7d774bc4df88bf848bcb796559b53ce
prerequisite-patch-id: 02021b74355b70debd344a6e445285c67dfef7d6
prerequisite-patch-id: c87fcf5a54f6805967cbf8ab107606c57d9ecf52
prerequisite-patch-id: ac7dee583d0ffa519c9d1cd89d27664bca68d8c1
prerequisite-patch-id: eac59ae2ea85d2d51e5be1b03e88a5641cc12c22
prerequisite-patch-id: 13da42ad04dc8e2e3bd6a556a0be0e17cf23669b
prerequisite-patch-id: fd3f09fdb58ddc1c595ea014716851f4c8fca48c
prerequisite-patch-id: 55b398673bd7edefb85d383c82785b668588e9c2
-- 
2.14.5
Pedro Alves July 7, 2020, 1:29 a.m. | #4
On 7/7/20 2:27 AM, Pedro Alves wrote:
> The issue is that the remote target is unpushed while within scoped_restore_current_thread' dtor's


I meant ctor, not dtor.

> get_frame_id call, which results in threads being deleted.  However, back in

> scoped_restore_current_thread's ctor, we only increment the refcount after get_frame_id

> returns.  Incrementing the refcounts earlier fixes it.
Pedro Alves July 10, 2020, 11:02 p.m. | #5
On 7/6/20 8:02 PM, Pedro Alves wrote:
> This patch series fixes PR 26199, a GDB 10 blocker.

> 


I've merged this series now.