From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) by sourceware.org (Postfix) with ESMTPS id 1159E3858D28 for ; Wed, 3 Nov 2021 14:51:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1159E3858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm1-f44.google.com with SMTP id g191-20020a1c9dc8000000b0032fbf912885so2043039wme.4 for ; Wed, 03 Nov 2021 07:51:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:references:from:in-reply-to :content-transfer-encoding; bh=QaFiBuO48xsZVaoW/2XtJiukFoQFgn4M9mfF5e6n1vQ=; b=anBO7VtW0rlFZMOyJ/Uy+RZ2JWKlT55xAA5rfTZ/yKQwZYP3d3xAqU7OOr2LBo1QtW UuzEmMqQVjASu1czP61rSSN0Gf5fLhEPfTTy7s/AMXsJ1bv9Mtlb85qxwK8MPoYaiKmS IN4/2MMA8oojJv3oAw5XcOV4PfMcbXFmKxT8QIN1FsMIZhsjMdapOQatu/Q39vp7fuHM 9xygdrf1X5q3on6hQJ4PrA8oBrzMjlnh1w+ruirvXxiCgNhGfYzdYcZ0lBdBAHH/RytW Sx5xMjP6SW0aJtLBucPV8EEJfZnvB+OhkDfc8xRQJ4eKMXGihNIqq5lglKsebv48472g s/8A== X-Gm-Message-State: AOAM531XSPZAZ9IwSB6JNKElsCo/JqFTkBXCpYeAXCkPZ98PjJ03nEHQ SGHCUejkLs13unkwq4gCwRbIUpqmFv+LVg== X-Google-Smtp-Source: ABdhPJy+EtWZsCTVUSa/yUiSakBnTyuGye3kL7VjNGS4JXQrDW5EldA8Kh0ZoX3jGTJqQNg3N4JWaA== X-Received: by 2002:a1c:1fcf:: with SMTP id f198mr15787508wmf.66.1635951098946; Wed, 03 Nov 2021 07:51:38 -0700 (PDT) Received: from ?IPV6:2001:8a0:f912:1a00:fb57:3faf:e98:b979? ([2001:8a0:f912:1a00:fb57:3faf:e98:b979]) by smtp.gmail.com with ESMTPSA id a134sm2336300wmd.9.2021.11.03.07.51.37 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 Nov 2021 07:51:37 -0700 (PDT) Message-ID: <4d143a57-1f9f-d695-eb03-af5496dc3c5a@palves.net> Date: Wed, 3 Nov 2021 14:51:36 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.2.1 Subject: Re: [PATCH 2/4] gdb, infrun, record: fix hang when step-over fails with no-history Content-Language: en-US To: Markus Metzger , gdb-patches@sourceware.org References: <20210316093501.936148-1-markus.t.metzger@intel.com> <20210316093501.936148-3-markus.t.metzger@intel.com> From: Pedro Alves In-Reply-To: <20210316093501.936148-3-markus.t.metzger@intel.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_SHORT, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Wed, 03 Nov 2021 14:51:42 -0000 On 2021-03-16 09:34, Markus Metzger via Gdb-patches wrote: > When trying to step over a breakpoint at the end of the trace while > another thread is replaying, the step-over will fail with no-history. Some information seems missing here. The no-history event is for the other thread that is replaying, right? We don't use displaced stepping when using a record target, so why did that other thread report the no-history event? Without displaced stepping, GDB will only resume the thread stepping over the breakpoint, so I'm confused on how the other thread's position in the replay log affects the stepping thread. > This does not clear step_over_info so a subsequent resume will cause GDB > to not resume the thread and expect a SIGTRAP to complete the step-over. > This will never come causing GDB to hang in the wait-for-event poll. > > This is a variant of the issue fixed in the parent commit. That commit > addressed the issue for a single-threaded process and fixed an issue with > reverse/replay stepping in general. > > This commit addresses the issue for a multi-threaded process. In this > case, the single-step does not complete. > > Finish an in-flight step-over when a thread stopped with NO_HISTORY. > Since we did not move, we will simply start the step-over again. > > gdb/ChangeLog: > 2021-03-02 Markus Metzger > > * infrun.c (finish_step_over): New declaration. > (handle_inferior_event): Call finish_step_over. > > gdb/testsuite/ChangeLog: > 2021-03-02 Markus Metzger > > * gdb.btrace/multi-thread-break-hang.exp: New file. > --- > gdb/infrun.c | 6 ++ > .../gdb.btrace/multi-thread-break-hang.exp | 92 +++++++++++++++++++ > 2 files changed, 98 insertions(+) > create mode 100644 gdb/testsuite/gdb.btrace/multi-thread-break-hang.exp > > diff --git a/gdb/infrun.c b/gdb/infrun.c > index 591fda93d21..e79094ad2b2 100644 > --- a/gdb/infrun.c > +++ b/gdb/infrun.c > @@ -95,6 +95,8 @@ static void resume (gdb_signal sig); > > static void wait_for_inferior (inferior *inf); > > +static int finish_step_over (struct execution_control_state *ecs); > + > /* Asynchronous signal handler registered as event loop source for > when we have pending events ready to be passed to the core. */ > static struct async_event_handler *infrun_async_inferior_event_token; > @@ -5543,6 +5545,10 @@ handle_inferior_event (struct execution_control_state *ecs) > return; > > gdb::observers::no_history.notify (); > + > + /* Cancel an in-flight step-over. It will not succeed since we > + won't be able to step at the end of the execution history. */ > + finish_step_over (ecs); > stop_waiting (ecs); > return; > } > diff --git a/gdb/testsuite/gdb.btrace/multi-thread-break-hang.exp b/gdb/testsuite/gdb.btrace/multi-thread-break-hang.exp > new file mode 100644 > index 00000000000..8496de5b36c > --- /dev/null > +++ b/gdb/testsuite/gdb.btrace/multi-thread-break-hang.exp > @@ -0,0 +1,92 @@ > +# This testcase is part of GDB, the GNU debugger. > +# > +# Copyright 2021 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 . > + > +# Test that we cancel an in-flight step-over at the end of the execution > +# history as long as some other thread is still replaying. > +# > +# This used to cause GDB to hang in poll (). > + > +if { [skip_btrace_tests] } { > + unsupported "target does not support record-btrace" > + return -1 > +} > + > +standard_testfile multi-thread-step.c > +if [prepare_for_testing "failed to prepare" $testfile $srcfile {debug libs=-lpthread}] { Should use the "pthreads" option as in "{debug pthreads}" instead of linking with -lpthread directly. > + return -1 > +} > + > +if ![runto_main] { > + untested "failed to run to main" > + return -1 > +} > + > +# Set up breakpoints. > +set bp_1 [gdb_get_line_number "bp.1" $srcfile] > +set bp_2 [gdb_get_line_number "bp.2" $srcfile] > + > +# Trace the code between the two breakpoints. > +gdb_breakpoint $srcfile:$bp_1 > +gdb_continue_to_breakpoint "continue to bp.1" ".*$srcfile:$bp_1\r\n.*" > + > +# Make sure GDB knows about the new thread. This is not necessary nowadays, as normal_stop always calls update_thread_list. > +gdb_test "info threads" ".*" > +gdb_test_no_output "record btrace" > + > +# We have two threads at or close to bp.1 but handled only one stop event. > +# Remove the breakpoint so we do not need to deal with the 2nd event. > +delete_breakpoints > +gdb_breakpoint $srcfile:$bp_2 > +gdb_continue_to_breakpoint "continue to bp.2" ".*$srcfile:$bp_2\r\n.*" > + > +# Determine the thread that reported the breakpoint. > +set thread "bad" > +gdb_test_multiple "thread" "thread" { > + -re "Current thread is \($decimal\).*\r\n$gdb_prompt $" { > + set thread $expect_out(1,string) > + } > +} This is fine, but FYI, it could be done with a single liner: set thread [get_integer_valueof "\$_thread" bad] > + > +# Determine the other thread. > +set other "bad" > +if { $thread == 1 } { > + set other 2 > +} elseif { $thread == 2 } { > + set other 1 > +} > + > +# This test works for scheduler-locking 'on' or 'step'; 'replay' would > +# implicitly stop replaying, avoiding the problem; 'off' would step one > +# and resume the other. The test would work for the current lock-step > +# implementation. What does the last sentence about "lock-step" mean? Also, I find "work" ambiguous. I take it here is means "exercises the original bug". How about saying that? > +gdb_test_no_output "set scheduler-locking step" > + > +# Start replaying the other thread. This will prevent stepping the thread > +# that reported the event. What is the "this" in "This will prevent"? Is it the use of "record goto" you're referring to, or something else? > +gdb_test "thread apply $other record goto begin" ".*" > +gdb_test "thread apply $other info record" "Replay in progress.*" > + > +# We're at a breakpoint so this triggers step-over. Since we're at the > +# end of the trace, the step will fail. What is "we" here? It's the "other" thread, not the stepping thread, right? Please clarify the comments. > +gdb_test "stepi" "No more reverse-execution history.*" "stepi.1" > + > +# We used to hang at the second step since step-over insisted on polling > +# the next event. > +gdb_test "stepi" "No more reverse-execution history.*" "stepi.2" > + > +# Do one more just in case. > +gdb_test "stepi" "No more reverse-execution history.*" "stepi.3" >