From patchwork Tue Mar 12 11:34:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Metzger, Markus T" X-Patchwork-Id: 87076 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 C9AF83858020 for ; Tue, 12 Mar 2024 11:35:46 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) by sourceware.org (Postfix) with ESMTPS id 35BF03858D39 for ; Tue, 12 Mar 2024 11:34:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 35BF03858D39 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 35BF03858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.12 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710243276; cv=none; b=lVKzwoMZcvtC+I13oj5VBIdp8Nms8LCRCTbFuUCfgKBNbEJA8CMucb51iIioP9cXUibW4fR04j4HxXCZ6emjGtB7iqr7nLXezo9MLIHZD5TZLviv4zo7CSGuUFdSZgdO5r/AYwl6jaLluGY15tUjENQNtc+pZqOEi8Zn8iFc6Pw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1710243276; c=relaxed/simple; bh=gLZanBYSGaBp+zZ3LIRFvwdw+M+J9N1R5zE6Z018nnE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=sE0mKIaNN9OXkNUXc+BGaH1rmPLrv99iyXgpY3OBh7pjcdF5TlFeQeqEnMu9Z212WUDsmgSEohAxqQlxNuIELaIjOyo0IBQ5jq5buwwJCLbR/QDvt/8JSeOSwzu0Y3k7V5WQeyl3GEIpAsv6BZmuAFUNTqXcn1QcvNl9vV3XI7U= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1710243273; x=1741779273; h=from:to:subject:date:message-id:in-reply-to:references: mime-version:content-transfer-encoding; bh=gLZanBYSGaBp+zZ3LIRFvwdw+M+J9N1R5zE6Z018nnE=; b=T/3uwtzJX3Ap7lVE3lao4P1/vAu0BOp2lPkLgTOudj1L792dsiTX8Mdc xTZFrqnqcOS++ItQe8nOa4jbPRYYhzcQ2E3VLYvDLWwc66OSPrivXC7zY qizY316wdF883yNrAR3k0AR9RwSSK81WRZKT5tYr7u08efIFmVdRxLhkM XkB2drI/S5rj6+nUiWpf+xZrPyeBE5MOzFjUBQCG539i7PzcCUhcFlNE+ GGhI8w3VDlofO9CKe/XmGmQx9KIPvydhO5cvpBEfn+LPEEs9tvTm9t/1x gQPZVFn4Go2HutwxPjbXgtvVw61KWztKdFivwRRYoOj/QbzlmOptNj1Ib Q==; X-IronPort-AV: E=McAfee;i="6600,9927,11010"; a="8709962" X-IronPort-AV: E=Sophos;i="6.07,119,1708416000"; d="scan'208";a="8709962" Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Mar 2024 04:34:33 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.07,119,1708416000"; d="scan'208";a="15999871" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by fmviesa005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Mar 2024 04:34:31 -0700 From: Markus Metzger To: gdb-patches@sourceware.org Subject: [PATCH v4 2/4] gdb, infrun, record: fix hang when step-over fails with no-history Date: Tue, 12 Mar 2024 11:34:21 +0000 Message-Id: <20240312113423.3543956-3-markus.t.metzger@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240312113423.3543956-1-markus.t.metzger@intel.com> References: <20240312113423.3543956-1-markus.t.metzger@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.0 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org 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. 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. Reviewed-By: Guinevere Larsen --- gdb/infrun.c | 14 ++++ .../gdb.btrace/multi-thread-break-hang.exp | 84 +++++++++++++++++++ 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 f38d96b64df..eb5164b4066 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -78,6 +78,8 @@ #include "disasm.h" #include "interps.h" +struct execution_control_state; + /* Prototypes for local functions */ static void sig_print_info (enum gdb_signal); @@ -109,6 +111,8 @@ static bool step_over_info_valid_p (void); static bool schedlock_applies (struct thread_info *tp); +static int finish_step_over (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; @@ -6535,6 +6539,16 @@ handle_inferior_event (struct execution_control_state *ecs) return; interps_notify_no_history (); + + /* 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 may call restart_threads, which may change the + current thread. make sure we leave the event thread as the + current thread. */ + scoped_restore_current_thread restore_thread; + 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..33edcf05612 --- /dev/null +++ b/gdb/testsuite/gdb.btrace/multi-thread-break-hang.exp @@ -0,0 +1,84 @@ +# This testcase is part of GDB, the GNU debugger. +# +# Copyright 2024 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 (). + +require allow_btrace_tests + +standard_testfile multi-thread-step.c +if [prepare_for_testing "failed to prepare" $testfile $srcfile {debug pthreads}] { + return -1 +} + +if ![runto_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.*" + +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 [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 requires scheduler-locking 'on' or 'step'; 'replay' would +# implicitly stop replaying, avoiding the problem; 'off' would step one +# and resume the other. +# +# With the current record-btrace implementation that steps all resumed +# threads in lock-step, 'off' might actually pass but we don't want to +# bake that behavior into tests. +gdb_test_no_output "set scheduler-locking step" + +# Start replaying the other thread. This will prevent stepping the thread +# that reported the event. +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. +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"