From patchwork Sat Dec 3 21:13:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61455 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 D84C43858291 for ; Sat, 3 Dec 2022 21:14:10 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by sourceware.org (Postfix) with ESMTPS id 0F5E73858D39 for ; Sat, 3 Dec 2022 21:13:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0F5E73858D39 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-f45.google.com with SMTP id ay8-20020a05600c1e0800b003d0808d2826so3939762wmb.1 for ; Sat, 03 Dec 2022 13:13:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3/XM98hopY1uti+3dEYPcS9TeeducasKhp1aIvfPqaA=; b=Zl5Z9IjEDdC0KhMoUDSFoXIYALPfPXiFjhUlT4C4IxPWfkcb3tA93UWyFnViIHRpq8 7YieCR2jBAVTSViuMVbzL8joLGs0uocy7glou16Gc4/15DpNhv5M09ixN3mQEvxoID8Y 0/Iat7Gu/HhNSl3Oqpbeqpw2rg6ZHxaUDncewmkgkaygbriQdfbYwOUmEoXG52ikcrv9 2IJ6qvR3eeI0sD0m9Bx7M5H8huKpbBSeH7v29dnM59bVPl+1ZgkWgr+xeT5EpU/u7WtW hnx90NbjQ1K8T9OLK4bfgyKEExWIEKj7H7PfZZc3aAOloyHIa47RgStVzzURFxxJY9Ws wSRA== X-Gm-Message-State: ANoB5plmAYzR/t31P0aPaANN6lWey9HhdB+s+nCs+7OwirTrOgl478sx rnzp9vyk5/a+twSQAI8rjBCcQ/IXNkkykQ== X-Google-Smtp-Source: AA0mqf4VNuOB02zroE3A2+A1ZIE37FTWpXacOxiK3RM0z3YxtEIeqsDdv+AnpLjQwO9e4Wsdy28JXQ== X-Received: by 2002:a05:600c:1d23:b0:3d0:8193:c1c with SMTP id l35-20020a05600c1d2300b003d081930c1cmr7562015wms.143.1670102022774; Sat, 03 Dec 2022 13:13:42 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id i10-20020a1c540a000000b003cfc02ab8basm15774332wmb.33.2022.12.03.13.13.42 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:42 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 1/6] Tweak "Using the running image of ..." output Date: Sat, 3 Dec 2022 21:13:33 +0000 Message-Id: <20221203211338.2264994-2-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-9.8 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" Currently, "info files" and "info program" on a few native targets show: (gdb) info files Symbols from "/home/pedro/gdb/tests/threads". Native process: Using the running image of child Thread 0x7ffff7d89740 (LWP 1097968). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... (gdb) info program Using the running image of child Thread 0x7ffff7d89740 (LWP 1097968). ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Program stopped at 0x555555555278. ... This patch changes them to: (gdb) info files Symbols from "/home/pedro/gdb/tests/threads". Native process: Using the running image of child process 1097968. ^^^^^^^^^^^^^^^ ... (gdb) info program Using the running image of child process 1097968. ^^^^^^^^^^^^^^^ Program stopped at 0x555555555278. ... ... which I think makes a lot more sense in this context. The "info program" manual entry even says: "Display information about the status of your program: whether it is running or not, what process it is, and why it stopped." ^^^^^^^^^^^^^ This change affects ptrace targets, procfs targets, and Windows. Change-Id: I6aab061ff494a84ba3398cf98fd49efd7a6ec1ca --- gdb/inf-ptrace.c | 2 +- gdb/nto-procfs.c | 2 +- gdb/procfs.c | 2 +- gdb/windows-nat.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index ab669a7acc2..ade07f41ef4 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -522,7 +522,7 @@ inf_ptrace_target::files_info () gdb_printf (_("\tUsing the running image of %s %s.\n"), inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid).c_str ()); + target_pid_to_str (ptid_t (inf->pid)).c_str ()); } std::string diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c index 4a2968ea179..fe9aa8dabfa 100644 --- a/gdb/nto-procfs.c +++ b/gdb/nto-procfs.c @@ -658,7 +658,7 @@ nto_procfs_target::files_info () gdb_printf ("\tUsing the running image of %s %s via %s.\n", inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid).c_str (), + target_pid_to_str (ptid_t (inf->pid)).c_str (), (nodestr != NULL) ? nodestr : "local node"); } diff --git a/gdb/procfs.c b/gdb/procfs.c index ac3d60ebf1c..ffc26c8fb9e 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -2533,7 +2533,7 @@ procfs_target::files_info () gdb_printf (_("\tUsing the running image of %s %s via /proc.\n"), inf->attach_flag? "attached": "child", - target_pid_to_str (inferior_ptid).c_str ()); + target_pid_to_str (ptid_t (inf->pid)).c_str ()); } /* Make it die. Wait for it to die. Clean up after it. Note: this diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index b3329cd1a0d..ee4e78bdabf 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -2157,7 +2157,7 @@ windows_nat_target::files_info () gdb_printf ("\tUsing the running image of %s %s.\n", inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid).c_str ()); + target_pid_to_str (ptid_t (inf->pid)).c_str ()); } /* Modify CreateProcess parameters for use of a new separate console. From patchwork Sat Dec 3 21:13:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61453 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 8527A385781F for ; Sat, 3 Dec 2022 21:14:05 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by sourceware.org (Postfix) with ESMTPS id 6617A3858422 for ; Sat, 3 Dec 2022 21:13:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6617A3858422 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-f49.google.com with SMTP id ay27-20020a05600c1e1b00b003d070f4060bso7057250wmb.2 for ; Sat, 03 Dec 2022 13:13:48 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AzZlfw/YJkzAqhrvTcFM4YDRdfYSmj6nkx9Is7WMQ2Q=; b=BAFS67SHUbxrtdILCv7GLlCbhGcEvrwp0MzAaowZxMgf2Q55Ynb+JDT0hGqUBr/PFU eb1j3jqpTgPoZt7AmYg1tKGk7feL9n9EHsjDi6bTMNZfOFsAY2ABDuGjGcbLUUsb+nzi 6/orNTYs5Us1cvj3zd7jU/ja5g15CIEV5SmV3pAPdYXImO2i9DbEXmhg+cjstB2J865Z 7HPXyCESEFsSWPekZE1xBcJWgrnE5Yk4ZeyDdQVEFeWtX3DOsGbOQM0Wkm2TYXVaKVHJ cUVpFxzgp+YaP1biNdl3oSHwxyjiLvWPMZzUHTjXyCx6ediLucSJ60VKzMejufkZWlno +QoQ== X-Gm-Message-State: ANoB5plXqIRfgQGp1NUT2+LZZNd3LKcUaQxRrXR2Tx0iltBUIhciMEVI 3ug4QNo2YPoG5YhBFEeCGKeg4bxzk6NpeA== X-Google-Smtp-Source: AA0mqf5mDKGyKAe1Nh9BM1iZD5VVACReiQafegRS7j8RfOCw5ZsSb2lUhXHvzlgDNmk1GtpgVG+VFw== X-Received: by 2002:a05:600c:3587:b0:3cf:a9c2:2b04 with SMTP id p7-20020a05600c358700b003cfa9c22b04mr55267253wmq.152.1670102026727; Sat, 03 Dec 2022 13:13:46 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id g13-20020a05600c310d00b003a2f2bb72d5sm20621933wmo.45.2022.12.03.13.13.46 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:46 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 2/6] Convert previous_inferior_ptid to strong reference to thread_info Date: Sat, 3 Dec 2022 21:13:34 +0000 Message-Id: <20221203211338.2264994-3-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" I originally wrote this patch, because while working on some other patch, I spotted a regression in the gdb.multi/multi-target-no-resumed.exp.exp testcase. Debugging the issue, I realized that the problem was related to how I was using previous_inferior_ptid to look up the thread the user had last selected. The problem is that previous_inferior_ptid alone doesn't tell you which target that ptid is from, and I was just always using the current target, which was incorrect. Two different targets may have threads with the same ptid. I decided to fix this by replacing previous_inferior_ptid with a strong reference to the thread, called previous_thread. I have since found a new motivation for this change -- I would like to tweak "info program" to not rely on get_last_target_status returning a ptid that still exists in the thread list. With both the follow_fork changes later in this series, and the step-over-thread-exit changes, that can happen, as we'll delete threads and not clear the last waitstatus. A new update_previous_thread function is added that can be used to update previous_thread from inferior_ptid. This must be called in several places that really want to get rid of previous_thread thread, and reset the thread id counter, otherwise we get regressions like these: (gdb) info threads -gid Id GId Target Id Frame - * 1 1 Thread 2974541.2974541 "tids-gid-reset" main () at src/gdb/testsuite/gdb.multi/tids-gid-reset.c:21 - (gdb) PASS: gdb.multi/tids-gid-reset.exp: single-inferior: after restart: info threads -gid + * 1 2 Thread 2958361.2958361 "tids-gid-reset" main () at src/gdb/testsuite/gdb.multi/tids-gid-reset.c:21 + (gdb) FAIL: gdb.multi/tids-gid-reset.exp: single-inferior: after restart: info threads -gid and: Core was generated by `build/gdb/testsuite/outputs/gdb.reverse/sigall-precsave/si'. Program terminated with signal SIGTRAP, Trace/breakpoint trap. #0 gen_ABRT () at src/gdb/testsuite/gdb.reverse/sigall-reverse.c:398 398 kill (getpid (), SIGABRT); +[Current thread is 1 (LWP 2662066)] Restored records from core file build/gdb/testsuite/outputs/gdb.reverse/sigall-precsave/sigall.precsave. #0 gen_ABRT () at src/gdb/testsuite/gdb.reverse/sigall-reverse.c:398 398 kill (getpid (), SIGABRT); continue Continuing. -Program received signal SIGABRT, Aborted. +Thread 1 received signal SIGABRT, Aborted. 0x00007ffff7dfd55b in kill () at ../sysdeps/unix/syscall-template.S:78 78 ../sysdeps/unix/syscall-template.S: No such file or directory. -(gdb) PASS: gdb.reverse/sigall-precsave.exp: sig-test-1: get signal ABRT +(gdb) FAIL: gdb.reverse/sigall-precsave.exp: sig-test-1: get signal ABRT I.e., GDB was failing to restart the thread counter back to 1, because the previous_thread thread was being help due to the strong reference. Tested on GNU/Linux native, gdbserver and gdbserver + "maint set target-non-stop on". gdb/ChangeLog: yyyy-mm-dd Pedro Alves * infcmd.c (kill_command, detach_command, disconnect_command): Call update_previous_thread. * infrun.c (previous_inferior_ptid): Delete. (previous_thread): New. (update_previous_thread): New. (proceed, init_wait_for_inferior): Call update_previous_thread. (normal_stop): Adjust to compare previous_thread and inferior_thread. Call update_previous_thread. * infrun.h (update_previous_thread): Declare. * target.c (target_pre_inferior, target_preopen): Call update_previous_thread. Change-Id: I42779a1ee51a996fa1e8f6e1525c6605dbfd42c7 --- gdb/infcmd.c | 5 +++++ gdb/infrun.c | 43 ++++++++++++++++++++++++++++--------------- gdb/infrun.h | 4 ++++ gdb/target.c | 5 +++++ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/gdb/infcmd.c b/gdb/infcmd.c index a27d3577b3a..bffe8d554e7 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2456,6 +2456,8 @@ kill_command (const char *arg, int from_tty) target_kill (); bfd_cache_close_all (); + update_previous_thread (); + if (print_inferior_events) gdb_printf (_("[Inferior %d (%s) killed]\n"), infnum, pid_str.c_str ()); @@ -2816,6 +2818,8 @@ detach_command (const char *args, int from_tty) target_detach (current_inferior (), from_tty); + update_previous_thread (); + /* The current inferior process was just detached successfully. Get rid of breakpoints that no longer make sense. Note we don't do this within target_detach because that is also used when @@ -2854,6 +2858,7 @@ disconnect_command (const char *args, int from_tty) target_disconnect (args, from_tty); no_shared_libraries (nullptr, from_tty); init_thread_list (); + update_previous_thread (); if (deprecated_detach_hook) deprecated_detach_hook (); } diff --git a/gdb/infrun.c b/gdb/infrun.c index c67458b30b6..a936f18fbb1 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -151,8 +151,18 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty, /* proceed and normal_stop use this to notify the user when the inferior stopped in a different thread than it had been running in. */ +static thread_info_ref previous_thread; -static ptid_t previous_inferior_ptid; +/* See infrun.h. */ + +void +update_previous_thread () +{ + if (inferior_ptid == null_ptid) + previous_thread = nullptr; + else + previous_thread = thread_info_ref::new_reference (inferior_thread ()); +} /* If set (default for legacy reasons), when following a fork, GDB will detach from one of the fork branches, child or parent. @@ -3150,7 +3160,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) } /* We'll update this if & when we switch to a new thread. */ - previous_inferior_ptid = inferior_ptid; + update_previous_thread (); regcache = get_current_regcache (); gdbarch = regcache->arch (); @@ -3433,7 +3443,7 @@ init_wait_for_inferior (void) nullify_last_target_wait_ptid (); - previous_inferior_ptid = inferior_ptid; + update_previous_thread (); } @@ -8647,21 +8657,24 @@ normal_stop (void) the current thread back to the thread the user had selected right after this event is handled, so we're not really switching, only informing of a stop. */ - if (!non_stop - && previous_inferior_ptid != inferior_ptid - && target_has_execution () - && last.kind () != TARGET_WAITKIND_SIGNALLED - && last.kind () != TARGET_WAITKIND_EXITED - && last.kind () != TARGET_WAITKIND_NO_RESUMED) + if (!non_stop) { - SWITCH_THRU_ALL_UIS () + if ((last.kind () != TARGET_WAITKIND_SIGNALLED + && last.kind () != TARGET_WAITKIND_EXITED + && last.kind () != TARGET_WAITKIND_NO_RESUMED) + && target_has_execution () + && previous_thread != inferior_thread ()) { - target_terminal::ours_for_output (); - gdb_printf (_("[Switching to %s]\n"), - target_pid_to_str (inferior_ptid).c_str ()); - annotate_thread_changed (); + SWITCH_THRU_ALL_UIS () + { + target_terminal::ours_for_output (); + gdb_printf (_("[Switching to %s]\n"), + target_pid_to_str (inferior_ptid).c_str ()); + annotate_thread_changed (); + } } - previous_inferior_ptid = inferior_ptid; + + update_previous_thread (); } if (last.kind () == TARGET_WAITKIND_NO_RESUMED) diff --git a/gdb/infrun.h b/gdb/infrun.h index c711b9b21cc..acaec9b5064 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -117,6 +117,10 @@ enum exec_direction_kind /* The current execution direction. */ extern enum exec_direction_kind execution_direction; +/* Call this to point 'previous_thread' at the thread returned by + inferior_thread, or at nullptr, if there's no selected thread. */ +extern void update_previous_thread (); + extern void start_remote (int from_tty); /* Clear out all variables saying what to do when inferior is diff --git a/gdb/target.c b/gdb/target.c index 1dd0f42af7d..f781f7e4f96 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2502,6 +2502,8 @@ target_pre_inferior (int from_tty) current_inferior ()->highest_thread_num = 0; + update_previous_thread (); + agent_capability_invalidate (); } @@ -2530,6 +2532,9 @@ target_preopen (int from_tty) error (_("Program not killed.")); } + /* Release reference to old previous thread. */ + update_previous_thread (); + /* Calling target_kill may remove the target from the stack. But if it doesn't (which seems like a win for UDI), remove it now. */ /* Leave the exec target, though. The user may be switching from a From patchwork Sat Dec 3 21:13:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61454 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 D13383855146 for ; Sat, 3 Dec 2022 21:14:06 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) by sourceware.org (Postfix) with ESMTPS id A03163858416 for ; Sat, 3 Dec 2022 21:13:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A03163858416 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-f41.google.com with SMTP id ja4-20020a05600c556400b003cf6e77f89cso6600800wmb.0 for ; Sat, 03 Dec 2022 13:13:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=OFfJYRHDqdP3V16oWIXdtbc9i26tY6qFbHoYLqpl6xo=; b=tyLZLYbbElSoV8aedpwHsfDEB7JQNQM3mRRpPhoyxEWq+SGiD5FcSkJIGygbGxtLe4 4bI+ey4yhCNGd467/4MxXE7kPM3NFLPQ2U4YCJcqbPFnq90e3TTzP0flU3iGQP/ooRMO QdSPuqLep5D57pfbKwTTD0DL40CWXuenRzAKG+OlYKx4l/fQLzzNzZwyYfWnyjZfA68V dPFjAXTw/tQEo2loN+CppZHAI1TRLeVgHlc/R3RHWgv40UioAdZCzGu2gCrL7IuOXKnb t4dok66QpX1fQI3V27nsPOVLSPxu9fnlx2bDoBO8SauDJPMD39Yb2vg6vADbGYZnNScn pi4A== X-Gm-Message-State: ANoB5pnpY/YnvFVGJqRsUorUtBvRLOa82UbnOgt9oqpEdl9GRhKHOdYu OC+c4c731ZOg4FMmSHinL+cUFiu9x90DBg== X-Google-Smtp-Source: AA0mqf4Aghwc7Aq7s2ndnRXK/4Y0hVz4x5JEvu3SVUSxfopUq5MtvPmHsCXLkrh7e5M0hgfO9yi/Fw== X-Received: by 2002:a1c:7513:0:b0:3cf:8896:e1c9 with SMTP id o19-20020a1c7513000000b003cf8896e1c9mr58225351wmc.119.1670102028115; Sat, 03 Dec 2022 13:13:48 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id b6-20020a5d6346000000b00242442c8ebdsm5401065wrw.111.2022.12.03.13.13.47 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:47 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 3/6] Improve "info program" Date: Sat, 3 Dec 2022 21:13:35 +0000 Message-Id: <20221203211338.2264994-4-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" With gdb.base/catch-follow-exec.exp, we currently see: ~~~~~~~~~~~~~~~ (gdb) continue Continuing. process 693251 is executing new program: /usr/bin/ls [New inferior 2] [New process 693251] [Switching to process 693251] Thread 2.1 "ls" hit Catchpoint 2 (exec'd /usr/bin/ls), 0x00007ffff7fd0100 in _start () from /lib64/ld-linux-x86-64.so.2 (gdb) info prog No selected thread. ~~~~~~~~~~~~~~~ Note the "No selected thread" output. That is totally bogus, because there _is_ a selected thread. What GDB really means, is that it can't find the thread that had the latest (user-visible) stop. And that happens because "info program" gets that info from get_last_target_status, and the last target status has been cleared. However, GDB also checks if there is a selected thread, here: if (ptid == null_ptid || ptid == minus_one_ptid) error (_("No selected thread.")); .. the null_ptid part. That is also bogus, because what matters is the thread that last reported a stop, not the current thread: - in all-stop mode, "info program" displays info about the last stop. That may have happened on a thread different from the selected thread. - in non-stop mode, because all threads are controlled individually, "info program" shows info about the last stop of the selected thread. The current code already behaves this way, though in a poor way. This patch reimplements it, such that the all-stop version now finds the thread that last reported an event via the 'previous_thread' strong reference. Being a strong reference means that if that thread has exited since the event was reported, 'previous_thread' will still point to it, so we can say that the thread exited meanwhile. The patch also extends "info program" output a little, to let the user know which thread we are printing info for. For example, for the gdb.base/catch-follow-exec.exp case we shown above, we now get: (gdb) info prog Last stopped for thread 2.1 (process 710867). Using the running image of child process 710867. Program stopped at 0x7ffff7fd0100. It stopped at breakpoint 2. Type "info stack" or "info registers" for more information. (gdb) while in non-stop mode, we get: (gdb) info prog Selected thread 2.1 (process 710867). Using the running image of child process 710867. Program stopped at 0x7ffff7fd0100. It stopped at breakpoint 2. Type "info stack" or "info registers" for more information. (gdb) In both cases, the first line of output is new. The existing code considered these running/exited cases as an error, but I think that that's incorrect, since this is IMO just plain execution info as well. So the patch makes those cases regular prints, not errors. If the thread is running, we get, in non-stop mode: (gdb) info prog Selected thread 2.1 (process 710867). Selected thread is running. ... and in all-stop: (gdb) info prog Last stopped for thread 2.1 (process 710867). Thread is now running. If the thread has exited, we get, in non-stop mode: (gdb) info prog Selected thread 2.1 (process 710867). Selected thread has exited. ... and in all-stop: (gdb) info prog Last stopped for thread 2.1 (process 710867). Thread has since exited. The gdb.base/info-program.exp testcase was much extended to test all-stop/non-stop and single-threaded/multi-threaded. Change-Id: I51d9d445f772d872af3eead3449ad4aa445781b1 --- gdb/infcmd.c | 79 ++++++++--- gdb/infrun.c | 13 +- gdb/infrun.h | 3 + gdb/testsuite/gdb.base/catch-follow-exec.exp | 17 ++- gdb/testsuite/gdb.base/info-program.c | 66 ++++++++++ gdb/testsuite/gdb.base/info-program.exp | 131 ++++++++++++++++--- 6 files changed, 263 insertions(+), 46 deletions(-) create mode 100644 gdb/testsuite/gdb.base/info-program.c diff --git a/gdb/infcmd.c b/gdb/infcmd.c index bffe8d554e7..744587504b3 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1937,37 +1937,74 @@ finish_command (const char *arg, int from_tty) static void info_program_command (const char *args, int from_tty) { - bpstat *bs; - int num, stat; - ptid_t ptid; - process_stratum_target *proc_target; + scoped_restore_current_thread restore_thread; - if (!target_has_execution ()) - { - gdb_printf (_("The program being debugged is not being run.\n")); - return; - } + thread_info *tp; + + /* In non-stop, since every thread is controlled individually, we'll + show execution info about the current thread. In all-stop, we'll + show execution info about the last stop. */ if (non_stop) { - ptid = inferior_ptid; - proc_target = current_inferior ()->process_target (); + if (!target_has_execution ()) + { + gdb_printf (_("The program being debugged is not being run.\n")); + return; + } + + if (inferior_ptid == null_ptid) + error (_("No selected thread.")); + + tp = inferior_thread (); + + gdb_printf (_("Selected thread %s (%s).\n"), + print_thread_id (tp), + target_pid_to_str (tp->ptid).c_str ()); + + if (tp->state == THREAD_EXITED) + { + gdb_printf (_("Selected thread has exited.\n")); + return; + } + else if (tp->state == THREAD_RUNNING) + { + gdb_printf (_("Selected thread is running.\n")); + return; + } } else - get_last_target_status (&proc_target, &ptid, nullptr); + { + tp = get_previous_thread (); + + if (tp == nullptr) + { + gdb_printf (_("The program being debugged is not being run.\n")); + return; + } - if (ptid == null_ptid || ptid == minus_one_ptid) - error (_("No selected thread.")); + switch_to_thread (tp); - thread_info *tp = find_thread_ptid (proc_target, ptid); + gdb_printf (_("Last stopped for thread %s (%s).\n"), + print_thread_id (tp), + target_pid_to_str (tp->ptid).c_str ()); - if (tp->state == THREAD_EXITED) - error (_("Invalid selected thread.")); - else if (tp->state == THREAD_RUNNING) - error (_("Selected thread is running.")); + if (tp->state == THREAD_EXITED) + { + gdb_printf (_("Thread has since exited.\n")); + return; + } + + if (tp->state == THREAD_RUNNING) + { + gdb_printf (_("Thread is now running.\n")); + return; + } + } - bs = tp->control.stop_bpstat; - stat = bpstat_num (&bs, &num); + int num; + bpstat *bs = tp->control.stop_bpstat; + int stat = bpstat_num (&bs, &num); target_files_info (); gdb_printf (_("Program stopped at %s.\n"), diff --git a/gdb/infrun.c b/gdb/infrun.c index a936f18fbb1..252f6e5eca5 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -149,8 +149,9 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty, } /* proceed and normal_stop use this to notify the user when the - inferior stopped in a different thread than it had been running - in. */ + inferior stopped in a different thread than it had been running in. + It can also be used to find for which thread normal_stop last + reported a stop. */ static thread_info_ref previous_thread; /* See infrun.h. */ @@ -164,6 +165,14 @@ update_previous_thread () previous_thread = thread_info_ref::new_reference (inferior_thread ()); } +/* See infrun.h. */ + +thread_info * +get_previous_thread () +{ + return previous_thread.get (); +} + /* If set (default for legacy reasons), when following a fork, GDB will detach from one of the fork branches, child or parent. Exactly which branch is detached depends on 'set follow-fork-mode' diff --git a/gdb/infrun.h b/gdb/infrun.h index acaec9b5064..18dd3c2ff60 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -121,6 +121,9 @@ extern enum exec_direction_kind execution_direction; inferior_thread, or at nullptr, if there's no selected thread. */ extern void update_previous_thread (); +/* Get a weak reference to 'previous_thread'. */ +extern thread_info *get_previous_thread (); + extern void start_remote (int from_tty); /* Clear out all variables saying what to do when inferior is diff --git a/gdb/testsuite/gdb.base/catch-follow-exec.exp b/gdb/testsuite/gdb.base/catch-follow-exec.exp index 08aab086b60..e2e19981c0f 100644 --- a/gdb/testsuite/gdb.base/catch-follow-exec.exp +++ b/gdb/testsuite/gdb.base/catch-follow-exec.exp @@ -31,16 +31,25 @@ proc catch_follow_exec { } { return -1 } - gdb_test "catch exec" \ - {Catchpoint [0-9]+ \(exec\)} + set bpnum "" + gdb_test_multiple "catch exec" "" { + -wrap -re "Catchpoint ($::decimal) \\\(exec\\\)" { + set bpnum $expect_out(1,string) + } + } + if {$bpnum == ""} { + return + } gdb_test_no_output "set follow-exec-mode new" gdb_test "continue" \ - ".*hit Catchpoint.*" + "Thread 2.1 .*hit Catchpoint $bpnum.*" + + set any "\[^\r\n\]*" gdb_test "info prog" \ - "No selected thread." + "Last stopped for thread 2.1 \\\($any\\\)\\..*It stopped at breakpoint $bpnum\\..*" } catch_follow_exec diff --git a/gdb/testsuite/gdb.base/info-program.c b/gdb/testsuite/gdb.base/info-program.c new file mode 100644 index 00000000000..fcb3c614f5f --- /dev/null +++ b/gdb/testsuite/gdb.base/info-program.c @@ -0,0 +1,66 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 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 . */ + +#ifdef USE_THREADS + +#include +#include +#include + +pthread_barrier_t barrier; +pthread_t child_thread; + +void * +child_function (void *arg) +{ + pthread_barrier_wait (&barrier); + + while (1) + usleep (100); + + pthread_exit (NULL); +} + +#endif /* USE_THREADS */ + +static void +done (void) +{ +} + +int +main (void) +{ +#ifdef USE_THREADS + int res; + + alarm (300); + + pthread_barrier_init (&barrier, NULL, 2); + + res = pthread_create (&child_thread, NULL, child_function, NULL); + pthread_barrier_wait (&barrier); +#endif /* USE_THREADS */ + + done (); + +#ifdef USE_THREADS + pthread_join (child_thread, NULL); +#endif /* USE_THREADS */ + + return 0; +} diff --git a/gdb/testsuite/gdb.base/info-program.exp b/gdb/testsuite/gdb.base/info-program.exp index 1496ea518dd..a1c779354b6 100644 --- a/gdb/testsuite/gdb.base/info-program.exp +++ b/gdb/testsuite/gdb.base/info-program.exp @@ -13,31 +13,124 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -standard_testfile normal.c +# Test "info program". +# +# We build both single-threaded and multi-threaded programs so that if +# the target doesn't support multi-threading, we still exercise the +# command. +# +# With the multi-threaded program, we test that in all-stop mode, GDB +# prints information about the last thread that stopped, not the +# current thread. In non-stop mode, the command always prints info +# about the selected thread, so we test that. -if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } { - return -1 -} +standard_testfile -if { ![runto_main] } { - return -1 -} +# Run the test with the given parameters: +# +# - THREADS: threads flavor, either single-threaded or +# multi-threaded. +# - NON-STOP: "set non-stop" value, "on" or "off". + +proc do_test { threads non-stop } { + save_vars { ::GDBFLAGS } { + append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\"" + clean_restart $::binfile-$threads + } + + gdb_test "info program" \ + "The program being debugged is not being run." \ + "info program before run" + + if { ![runto done] } { + return -1 + } + + if {${non-stop} == "on"} { + set thread_line "Selected" + } else { + set thread_line "Last stopped for" + } -gdb_test "info program" "Program stopped at $hex\.\r\nIt stopped at breakpoint $decimal\.\r\nType \"info stack\" or \"info registers\" for more information\." \ - "info program after run to main" + gdb_test "info program" \ + [multi_line \ + "$thread_line thread 1 (\[^\r\n\]+)\\." \ + ".*" \ + "Program stopped at $::hex\." \ + "It stopped at breakpoint $::decimal\." \ + "Type \"info stack\" or \"info registers\" for more information\."] \ + "info program after run to main" -# We don't really care where this step lands, so long as GDB reports -# that the inferior stopped due to a step in the subsequent test. -gdb_test "next" ".*" "step before info program" + # We don't really care where this step lands, so long as GDB reports + # that the inferior stopped due to a step in the subsequent test. + gdb_test "next" ".*" "step before info program" -gdb_test "info program" "Program stopped at $hex\.\r\nIt stopped after being stepped\.\r\nType \"info stack\" or \"info registers\" for more information\." \ - "info program after next" + gdb_test "info program" \ + [multi_line \ + "$thread_line thread 1 (\[^\r\n\]+)\\." \ + ".*" \ + "Program stopped at $::hex\." \ + "It stopped after being stepped\." \ + "Type \"info stack\" or \"info registers\" for more information\."] \ + "info program after next" -if {![runto_main]} { - return -1 + if {$threads == "mt"} { + gdb_test "thread 2" "\\\[Switching to thread 2 .*" + + if {${non-stop} == "on"} { + gdb_test "info program" \ + [multi_line \ + "$thread_line thread 2 (\[^\r\n\]+)\\." \ + "Selected thread is running\\."] \ + "info program after next, other thread" + } else { + gdb_test "info program" \ + [multi_line \ + "$thread_line thread 1 (\[^\r\n\]+)\\." \ + ".*" \ + "Program stopped at $::hex\." \ + "It stopped after being stepped\." \ + "Type \"info stack\" or \"info registers\" for more information\."] \ + "info program after next, other thread" + } + } + + gdb_test "kill" "" "kill program" \ + "Kill the program being debugged.*y or n. $" "y" + + gdb_test "info program" "The program being debugged is not being run." \ + "info program, after kill" + + if { ![runto done] } { + return -1 + } + + delete_breakpoints + + gdb_test "info program" \ + [multi_line \ + "$thread_line thread 1 (\[^\r\n\]+)\\." \ + ".*" \ + "Program stopped at $::hex\." \ + "It stopped at a breakpoint that has since been deleted\." \ + "Type \"info stack\" or \"info registers\" for more information\."] \ + "info program after deleting all breakpoints" } -delete_breakpoints +# Build executables and test them, one for each +# single-thread/multi-thread flavor. +foreach_with_prefix threads {st mt} { + set opts {debug} + if {$threads == "mt"} { + lappend opts pthreads "additional_flags=-DUSE_THREADS" + } -gdb_test "info program" "Program stopped at $hex\.\r\nIt stopped at a breakpoint that has since been deleted\.\r\nType \"info stack\" or \"info registers\" for more information\." \ - "info program after deleting all breakpoints" + if { [build_executable "failed to prepare $threads" \ + ${testfile}-${threads} ${srcfile} $opts] } { + continue + } + + foreach_with_prefix non-stop {on off} { + do_test ${threads} ${non-stop} + } +} From patchwork Sat Dec 3 21:13:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61456 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 27FC93853D42 for ; Sat, 3 Dec 2022 21:14:21 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) by sourceware.org (Postfix) with ESMTPS id 9E20D3858438 for ; Sat, 3 Dec 2022 21:13:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9E20D3858438 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-f46.google.com with SMTP id n7so5974382wms.3 for ; Sat, 03 Dec 2022 13:13:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Dsr+9AoUvPFwa2hcm3uz4M+gGC2r8Uj/DrG92NqpJsU=; b=tuxxmdVEcmtaH7/RbXWhDun56O+gajiS72k7WUHJMAjX+FwvB2dI1p61iWMtH5SGOO M1J+sjlgltovw0JKs1/nSdINSsa/Pgue+Mh6RNmHd2b5UcXtFQtoFWKvHWufnAJWwJpn 6efRV0HPj42G43tC1wT0Joi9uY0ZRqTZrt7pefJZrevWhENRQaQQ7mCSxIo2Oj8yJcJR VA6nZuaaPKNPMs/VP2DdS8PE5sMaxtc6GYJ5iN3Bj2zuzFtYGDmMQeXguDhmt9kt2bU3 GrVOPcOOhCVA8puXUcYY83XakPVfjGzXobP+026yjCbETI6ossyQlaigm/pbePxp3HUA mMhw== X-Gm-Message-State: ANoB5pn+jk0FCccv+EUai2T/eMI9+oJAZiLQrY4Ireha5HwYwlclpD1t m9RcLX9kmUxweN5au3MpiTaokz2FNFg1OQ== X-Google-Smtp-Source: AA0mqf6QKtvi9Olk9SGkDz1tCeEiFFUbbmtbTV03sOqMIFw05qaQEysUQgKUHVv+F09J+Nl7t99Uhw== X-Received: by 2002:a05:600c:1e1a:b0:3cf:7959:d8be with SMTP id ay26-20020a05600c1e1a00b003cf7959d8bemr49310064wmb.85.1670102030217; Sat, 03 Dec 2022 13:13:50 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id z10-20020a05600c0a0a00b003c70191f267sm19080543wmp.39.2022.12.03.13.13.49 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:49 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 4/6] Make follow_fork not rely on get_last_target_status Date: Sat, 3 Dec 2022 21:13:36 +0000 Message-Id: <20221203211338.2264994-5-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" Currently, if - you're in all-stop mode, - the inferior last stopped because of a fork catchpoint, when you next resume the program, gdb checks whether it had last stopped for a fork/vfork, and if so, a) if the current thread is the one that forked, gdb follows the parent/child, depending on "set follow-fork" mode. b) if the current thread is some other thread (because you switched threads meanwhile), gdb switches back to that thread, gdb follows the parent/child, and stops the resumption command. There's a problem in b), however -- if you have "set schedule-multiple off", which is the default, or "set scheduler-locking on", gdb will still switch back to the forking thread, even if you didn't want to resume it. For example, with: (gdb) catch fork (gdb) c * thread 1 stops for fork (gdb) thread 2 (gdb) set scheduler-locking on (gdb) c gdb switches back to thread 1, and follows the fork. Or with: (gdb) add-inferior -exec prog (gdb) inferior 2 (gdb) start (gdb) inferior 1 (gdb) catch fork (gdb) c * thread 1.1 stops for fork (gdb) inferior 2 (gdb) set schedule-multiple off # this is the default (gdb) c gdb switches back to thread 1.1, and follows the fork. Another issue is that, because follow_fork relies on get_last_target_status to find the thread that has a pending fork, it is possible to confuse it. For example, "run" or "start" call init_wait_for_inferior, which clears the last target status, so this: (gdb) catch fork (gdb) c * thread 1 stops for fork (gdb) add-inferior -exec prog (gdb) inferior 2 (gdb) start (gdb) set follow-fork child (gdb) inferior 1 (gdb) n ... does not follow to the fork child of inferior 1, because the get_last_target_status call in follow_fork doesn't return a TARGET_WAITKIND_FORKED. Thanks to Simon for this example. All of the above are fixed by this patch. It changes follow_fork to not look at get_last_target_status, but to instead iterate over the set of threads that the user is resuming, and find the one that has a pending_follow kind of fork/vfork. gdb.base/foll-fork.exp is augmented to exercise the last "start" scenario described above. The other cases will be exercised in the testcase added by the following patch. Change-Id: Ifcca77e7b2456277387f40660ef06cec2b93b97e --- gdb/infrun.c | 67 +++++++++++++++------------- gdb/testsuite/gdb.base/foll-fork.exp | 36 ++++++++++++++- 2 files changed, 71 insertions(+), 32 deletions(-) diff --git a/gdb/infrun.c b/gdb/infrun.c index 252f6e5eca5..617b6309e99 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -705,6 +705,15 @@ holding the child stopped. Try \"set detach-on-fork\" or \ return false; } +/* Set the last target status as TP having stopped. */ + +static void +set_last_target_status_stopped (thread_info *tp) +{ + set_last_target_status (tp->inf->process_target (), tp->ptid, + target_waitstatus {}.set_stopped (GDB_SIGNAL_0)); +} + /* Tell the target to follow the fork we're stopped at. Returns true if the inferior should be resumed; false, if the target for some reason decided it's best not to resume. */ @@ -729,32 +738,33 @@ follow_fork () if (!non_stop) { - process_stratum_target *wait_target; - ptid_t wait_ptid; - struct target_waitstatus wait_status; + thread_info *cur_thr = inferior_thread (); - /* Get the last target status returned by target_wait(). */ - get_last_target_status (&wait_target, &wait_ptid, &wait_status); - - /* If not stopped at a fork event, then there's nothing else to - do. */ - if (wait_status.kind () != TARGET_WAITKIND_FORKED - && wait_status.kind () != TARGET_WAITKIND_VFORKED) - return 1; + ptid_t resume_ptid + = user_visible_resume_ptid (cur_thr->control.stepping_command); + process_stratum_target *resume_target + = user_visible_resume_target (resume_ptid); - /* Check if we switched over from WAIT_PTID, since the event was - reported. */ - if (wait_ptid != minus_one_ptid - && (current_inferior ()->process_target () != wait_target - || inferior_ptid != wait_ptid)) + /* Check if there's a thread that we're about to resume, other + than the current, with an unfollowed fork/vfork. If so, + switch back to it, to tell the target to follow it (in either + direction). We'll afterwards refuse to resume, and inform + the user what happened. */ + for (thread_info *tp : all_non_exited_threads (resume_target, + resume_ptid)) { - /* We did. Switch back to WAIT_PTID thread, to tell the - target to follow it (in either direction). We'll - afterwards refuse to resume, and inform the user what - happened. */ - thread_info *wait_thread = find_thread_ptid (wait_target, wait_ptid); - switch_to_thread (wait_thread); - should_resume = false; + if (tp == cur_thr) + continue; + + if (tp->pending_follow.kind () != TARGET_WAITKIND_SPURIOUS) + { + infrun_debug_printf ("need to follow-fork [%s] first", + tp->ptid.to_string ().c_str ()); + + switch_to_thread (tp); + should_resume = false; + break; + } } } @@ -818,21 +828,16 @@ follow_fork () } else { - /* This makes sure we don't try to apply the "Switched - over from WAIT_PID" logic above. */ - nullify_last_target_wait_ptid (); - /* If we followed the child, switch to it... */ if (follow_child) { - thread_info *child_thr = find_thread_ptid (parent_targ, child); - switch_to_thread (child_thr); + tp = find_thread_ptid (parent_targ, child); + switch_to_thread (tp); /* ... and preserve the stepping state, in case the user was stepping over the fork call. */ if (should_resume) { - tp = inferior_thread (); tp->control.step_resume_breakpoint = step_resume_breakpoint; tp->control.step_range_start = step_range_start; @@ -871,6 +876,8 @@ follow_fork () break; } + if (!should_resume) + set_last_target_status_stopped (tp); return should_resume; } diff --git a/gdb/testsuite/gdb.base/foll-fork.exp b/gdb/testsuite/gdb.base/foll-fork.exp index 0ab2290c82c..885c791d016 100644 --- a/gdb/testsuite/gdb.base/foll-fork.exp +++ b/gdb/testsuite/gdb.base/foll-fork.exp @@ -212,15 +212,22 @@ set reading_in_symbols_re {(?:\r\nReading in symbols for [^\r\n]*)?} # Test the ability to catch a fork, specify that the child be # followed, and continue. Make the catchpoint permanent. -proc_with_prefix catch_fork_child_follow {} { +proc_with_prefix catch_fork_child_follow {second_inferior} { global gdb_prompt global srcfile global reading_in_symbols_re + if { $second_inferior && [use_gdb_stub] } { + return + } + if { ![setup] } { return } + # Get rid of the breakpoint at "main". + delete_breakpoints + set bp_after_fork [gdb_get_line_number "set breakpoint here"] gdb_test "catch fork" \ @@ -249,6 +256,29 @@ proc_with_prefix catch_fork_child_follow {} { "Temporary breakpoint.*, line $bp_after_fork.*" \ "set follow-fork child, tbreak" + if {$second_inferior} { + gdb_test "add-inferior" "Added inferior 2.*" "add inferior 2" + + gdb_test "inferior 2" "Switching to inferior 2.*" + + gdb_load $::binfile + + # Start it. This should not affect inferior 1, given "set + # schedule-multiple off" (default). GDB used to have a bug + # where "start" would clear the pending follow fork + # information of inferior 1. + gdb_test "start" "Starting program.*Temporary breakpoint .*" + + gdb_test "inferior 1" "Switching to inferior 1.*" + + # Verify that the catchpoint is still mentioned in an "info + # breakpoints", and further that the catchpoint still shows + # the captured process id. + gdb_test "info breakpoints" \ + ".*catchpoint.*keep y.*fork, process.*" \ + "info breakpoints, after starting second inferior" + } + set expected_re "\\\[Attaching after.* fork to.*\\\[Detaching after fork from" append expected_re ".* at .*$bp_after_fork.*" gdb_test "continue" $expected_re "set follow-fork child, hit tbreak" @@ -431,6 +461,8 @@ foreach_with_prefix follow-fork-mode {"parent" "child"} { # Catchpoint tests. -catch_fork_child_follow +foreach_with_prefix second_inferior {false true} { + catch_fork_child_follow $second_inferior +} catch_fork_unpatch_child tcatch_fork_parent_follow From patchwork Sat Dec 3 21:13:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61457 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 662AD385B517 for ; Sat, 3 Dec 2022 21:14:40 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by sourceware.org (Postfix) with ESMTPS id 2C1283858002 for ; Sat, 3 Dec 2022 21:13:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2C1283858002 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-f49.google.com with SMTP id ay27-20020a05600c1e1b00b003d070f4060bso7057362wmb.2 for ; Sat, 03 Dec 2022 13:13:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4sZ4MvFeaH5AY0KGn/CfnqawYXxlBTBETfY74xmjyAk=; b=udW663nYvNWdXmbrTgmRc0fy7BgQx3WMW9jv6ZeGNf8K7RZlIFUtuqti9kym+zqDu8 4FsgORmh5RgCLaT7DpCF2mnylgJlIpRJZPZMdrW47ButnrXB6+n/5L+owttGl2qG0uKX RU8gwH1fSDHLwi4E41Kh8EFik2de9+Xb+FS5ZAI2BWVPP53CdG8YSwjffMEwgEfe7/sf 1H2Yl1rRdsftAdIOE3t0SHSMZvCqVaa2PbXDI0CnbpnO6Qvcfj5+2JyLeeiagIWjMcuc kCw+aPx4iFpZ2Q0nNEzb0i5BLhaTvzjilLXNjNuRuMVqkNLF6MO8jTfEZjjxphm5EWT7 CCvA== X-Gm-Message-State: ANoB5pnphspAR2UmupMKurBsSpYvQye4hSrB5VFjzb8NjQL1RknSr3ks IVyQViVVXwwmHV58ua7uIXQsr91HZ1j/hQ== X-Google-Smtp-Source: AA0mqf7QoyA5LfSp6RZpHC/AGg26v8gMr2l8E6F8OxKq1FsAHAQftcqfhShs6McGBNG0VXQtLXIPWA== X-Received: by 2002:a05:600c:1e89:b0:3cf:774b:ce6f with SMTP id be9-20020a05600c1e8900b003cf774bce6fmr12054759wmb.133.1670102032131; Sat, 03 Dec 2022 13:13:52 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id co16-20020a0560000a1000b00241b6d27ef1sm10659199wrb.104.2022.12.03.13.13.51 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:51 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 5/6] all-stop "follow-fork parent" and selecting another thread Date: Sat, 3 Dec 2022 21:13:37 +0000 Message-Id: <20221203211338.2264994-6-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" With: - catch a fork in thread 1 - select thread 2 - set follow-fork child - next ... follow_fork notices that thread 1 had last stopped for a fork which hasn't been followed yet, and because thread 1 is not the current thread, GDB aborts the execution command, presenting the stop in thread 1. That makes sense, as only the forking thread (thread 1) survives in the child, so better stop and let the user decide how to proceed. However, with: - catch a fork in thread 1 - select thread 2 - set follow-fork parent << note difference here - next ... GDB does the same: follow_fork notices that thread 1 had last stopped for a fork which hasn't been followed yet, and because thread 1 is not the current thread, GDB aborts the execution command, presenting the stop in thread 1. Aborting/stopping in this case doesn't make sense to me. As we're following the parent, thread 2 will still continue to exist in the parent. What the child does after we've followed the parent shouldn't matter -- it can go on running free, be detached, etc., depending on "set schedule-multiple", "set detach-on-fork", etc. That does not influence the execution command that the user issued for the parent thread. So this patch changes GDB in that direction -- in follow_fork, if following the parent, and we've switched threads meanwhile, switch back to the unfollowed thread, follow it (stay with the parent), and don't abort/stop. If we're following a fork (as opposed to vfork), then switch back again to the thread that the user was trying to resume. If following a vfork, however, stay with the vforking-thread selected, as we will need to see a vfork_done event first, before we can resume any other thread. As I was working on this, I managed to end up calling target_resume for a solo-thread resume (to collect the vfork_done event), with scope_ptid pointing at the vfork parent thread, and inferior_ptid pointing to the vfork child. For a solo-thread resume, the scope_ptid argument to target_resume must the same as inferior_ptid. The mistake was caught by the assertion in target_resume, like so: ... [infrun] resume_1: step=0, signal=GDB_SIGNAL_0, trap_expected=0, current thread [1722839.1722839.0] at 0x5555555553c3 [infrun] do_target_resume: resume_ptid=1722839.1722939.0, step=0, sig=GDB_SIGNAL_0 ../../src/gdb/target.c:2661: internal-error: target_resume: Assertion `inferior_ptid.matches (scope_ptid)' failed. ... but I think it doesn't hurt to catch such a mistake earlier, hence the change in internal_resume_ptid. Change-Id: I896705506a16d2488b1bfb4736315dd966f4e412 --- gdb/infrun.c | 88 ++++++++- .../gdb.threads/foll-fork-other-thread.c | 84 +++++++++ .../gdb.threads/foll-fork-other-thread.exp | 172 ++++++++++++++++++ 3 files changed, 335 insertions(+), 9 deletions(-) create mode 100644 gdb/testsuite/gdb.threads/foll-fork-other-thread.c create mode 100644 gdb/testsuite/gdb.threads/foll-fork-other-thread.exp diff --git a/gdb/infrun.c b/gdb/infrun.c index 617b6309e99..f1afc4ba8e2 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -756,13 +756,56 @@ follow_fork () if (tp == cur_thr) continue; - if (tp->pending_follow.kind () != TARGET_WAITKIND_SPURIOUS) + /* follow_fork_inferior clears tp->pending_follow, and below + we'll need the value after the follow_fork_inferior + call. */ + target_waitkind kind = tp->pending_follow.kind (); + + if (kind != TARGET_WAITKIND_SPURIOUS) { infrun_debug_printf ("need to follow-fork [%s] first", tp->ptid.to_string ().c_str ()); switch_to_thread (tp); - should_resume = false; + + /* Set up inferior(s) as specified by the caller, and + tell the target to do whatever is necessary to follow + either parent or child. */ + if (follow_child) + { + /* The thread that started the execution command + won't exist in the child. Abort the command and + immediately stop in this thread, in the child, + inside fork. */ + should_resume = false; + } + else + { + /* Following the parent, so let the thread fork its + child freely, it won't influence the current + execution command. */ + if (follow_fork_inferior (follow_child, detach_fork)) + { + /* Target refused to follow, or there's some + other reason we shouldn't resume. */ + switch_to_thread (cur_thr); + set_last_target_status_stopped (cur_thr); + return false; + } + + /* If we're following a vfork, when we need to leave + the just-forked thread as selected, as we need to + solo-resume it to collect the VFORK_DONE event. + If we're following a fork, however, switch back + to the original thread that we continue stepping + it, etc. */ + if (kind != TARGET_WAITKIND_VFORKED) + { + gdb_assert (kind == TARGET_WAITKIND_FORKED); + switch_to_thread (cur_thr); + } + } + break; } } @@ -2200,6 +2243,29 @@ user_visible_resume_target (ptid_t resume_ptid) : current_inferior ()->process_target ()); } +/* Find a thread from the inferiors that we'll resume that is waiting + for a vfork-done event. */ + +static thread_info * +find_thread_waiting_for_vfork_done () +{ + gdb_assert (!target_is_non_stop_p ()); + + if (sched_multi) + { + for (inferior *inf : all_non_exited_inferiors ()) + if (inf->thread_waiting_for_vfork_done != nullptr) + return inf->thread_waiting_for_vfork_done; + } + else + { + inferior *cur_inf = current_inferior (); + if (cur_inf->thread_waiting_for_vfork_done != nullptr) + return cur_inf->thread_waiting_for_vfork_done; + } + return nullptr; +} + /* Return a ptid representing the set of threads that we will resume, in the perspective of the target, assuming run control handling does not require leaving some threads stopped (e.g., stepping past @@ -2240,14 +2306,18 @@ internal_resume_ptid (int user_step) Since we don't have that flexibility (we can only pass one ptid), just resume the first thread waiting for a vfork-done event we find (e.g. thread 2.1). */ - if (sched_multi) - { - for (inferior *inf : all_non_exited_inferiors ()) - if (inf->thread_waiting_for_vfork_done != nullptr) - return inf->thread_waiting_for_vfork_done->ptid; + thread_info *thr = find_thread_waiting_for_vfork_done (); + if (thr != nullptr) + { + /* If we have a thread that is waiting for a vfork-done event, + then we should have switched to it earlier. Calling + target_resume with thread scope is only possible when the + current thread matches the thread scope. */ + gdb_assert (thr->ptid == inferior_ptid); + gdb_assert (thr->inf->process_target () + == inferior_thread ()->inf->process_target ()); + return thr->ptid; } - else if (current_inferior ()->thread_waiting_for_vfork_done != nullptr) - return current_inferior ()->thread_waiting_for_vfork_done->ptid; return user_visible_resume_ptid (user_step); } diff --git a/gdb/testsuite/gdb.threads/foll-fork-other-thread.c b/gdb/testsuite/gdb.threads/foll-fork-other-thread.c new file mode 100644 index 00000000000..47e8b1c7389 --- /dev/null +++ b/gdb/testsuite/gdb.threads/foll-fork-other-thread.c @@ -0,0 +1,84 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2022 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 . */ + +#include +#include +#include +#include +#include +#include +#include + +/* Set by GDB. */ +volatile int stop_looping = 0; + +static void * +gdb_forker_thread (void *arg) +{ + int ret; + int stat; + pid_t pid = FORK_FUNC (); + + if (pid == 0) + _exit (0); + + assert (pid > 0); + + /* Wait for child to exit. */ + do + { + ret = waitpid (pid, &stat, 0); + } + while (ret == -1 && errno == EINTR); + + assert (ret == pid); + assert (WIFEXITED (stat)); + assert (WEXITSTATUS (stat) == 0); + + stop_looping = 1; + + return NULL; +} + +static void +sleep_a_bit (void) +{ + usleep (1000 * 50); +} + +int +main (void) +{ + int i; + int ret; + pthread_t thread; + + alarm (60); + + ret = pthread_create (&thread, NULL, gdb_forker_thread, NULL); + assert (ret == 0); + + while (!stop_looping) /* while loop */ + { + sleep_a_bit (); /* break here */ + sleep_a_bit (); /* other line */ + } + + pthread_join (thread, NULL); + + return 0; /* exiting here */ +} diff --git a/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp b/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp new file mode 100644 index 00000000000..ed62bfc54d9 --- /dev/null +++ b/gdb/testsuite/gdb.threads/foll-fork-other-thread.exp @@ -0,0 +1,172 @@ +# Copyright 2022 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 catching a vfork/fork in one thread, and then doing a "next" in +# another thread, in different combinations of "set follow-fork +# parent/child", and other execution modes. + +standard_testfile + +# Line where to stop the main thread. +set break_here_line [gdb_get_line_number "break here"] + +# Build executables, one for each fork flavor. +foreach_with_prefix fork_func {fork vfork} { + set opts [list debug pthreads additional_flags=-DFORK_FUNC=${fork_func}] + if { [build_executable "failed to prepare" \ + ${testfile}-${fork_func} ${srcfile} $opts] } { + return + } +} + +# Run the test with the given parameters: +# +# - FORK_FUNC: fork flavor, "fork" or "vfork". +# - FOLLOW: "set follow-fork" value, either "parent" or "child". +# - TARGET-NON-STOP: "maintenance set target-non-stop" value, "auto", "on" or +# "off". +# - NON-STOP: "set non-stop" value, "on" or "off". +# - DISPLACED-STEPPING: "set displaced-stepping" value, "auto", "on" or "off". + +proc do_test { fork_func follow target-non-stop non-stop displaced-stepping } { + save_vars { ::GDBFLAGS } { + append ::GDBFLAGS " -ex \"maintenance set target-non-stop ${target-non-stop}\"" + append ::GDBFLAGS " -ex \"set non-stop ${non-stop}\"" + clean_restart ${::binfile}-${fork_func} + } + + gdb_test_no_output "set displaced-stepping ${displaced-stepping}" + + if { ![runto_main] } { + return + } + + delete_breakpoints + + gdb_test "catch $fork_func" "Catchpoint .*" + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint mentions no process id. + gdb_test "info breakpoints" \ + ".*catchpoint.*keep y.*fork\[\r\n\]+" \ + "info breakpoints before fork" + + gdb_test "continue" \ + "Catchpoint \[0-9\]* \\(.?forked process \[0-9\]*\\),.*" \ + "explicit child follow, catch fork" + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint managed to capture a process id. + gdb_test "info breakpoints" \ + ".*catchpoint.*keep y.*fork, process.*" \ + "info breakpoints after fork" + + gdb_test "thread 1" "Switching to .*" + + gdb_test_no_output "set scheduler-locking on" + + # Advance the next-ing thread to the point where we'll execute the + # next. + gdb_test "break $::srcfile:$::break_here_line" "Breakpoint $::decimal at $::hex.*" + gdb_test "continue" "hit Breakpoint $::decimal, main.*" + + # Disable schedlock and step. The pending fork should no longer + # be pending afterwards. + + gdb_test "set scheduler-locking off" + + # Make sure GDB doesn't try to step over the breakpoint at PC + # first, we want to make sure that GDB doesn't lose focus of the + # step/next in this thread. A breakpoint would make GDB switch + # focus anyhow, thus hide a potential bug. + delete_breakpoints + + gdb_test_no_output "set follow-fork $follow" + + set any "\[^\r\n\]*" + + if {$follow == "child"} { + + # For fork, GDB detaches from the parent at follow-fork time. + # For vfork, GDB detaches from the parent at child exit/exec + # time. + if {$fork_func == "fork"} { + set detach_parent \ + [multi_line \ + "\\\[Detaching after $fork_func from parent process $any\\\]" \ + "\\\[Inferior 1 $any detached\\\]"] + } else { + set detach_parent "" + } + + gdb_test "next" \ + [multi_line \ + "\\\[Attaching after $any $fork_func to child $any\\\]" \ + "\\\[New inferior 2 $any\\\]" \ + "$detach_parent.*warning: Not resuming: switched threads before following fork child\\." \ + "\\\[Switching to $any\\\]" \ + ".*"] \ + "next aborts resumption" + + # The child should be stopped inside the fork implementation + # in the runtime. Exactly at which instruction/function is + # system dependent, but we can check that our + # "gdb_forker_thread" function appears in the backtrace. + gdb_test "bt" " in gdb_forker_thread ${any} at ${any}${::srcfile}:.*" + + # The child is now thread 1. + gdb_test "print \$_thread" " = 1" + + if {$fork_func == "fork"} { + gdb_test "continue" \ + [multi_line \ + "Continuing." \ + "\\\[Inferior 2 \\\(process $any\\\) exited normally\\\]"] \ + "continue to exit" + } else { + gdb_test "continue" \ + [multi_line \ + "Continuing." \ + "\\\[Detaching vfork parent process $any after child exit\\\]" \ + "\\\[Inferior 1 \\\(process $any\\\) detached\\\]" \ + "\\\[Inferior 2 \\\(process $any\\\) exited normally\\\]"] \ + "continue to exit" + } + } else { + gdb_test "next" \ + "\\\[Detaching after $fork_func from child process ${any}\\\].* other line .*" \ + "next to other line" + + gdb_test "print \$_thread" " = 1" + + gdb_test "continue" \ + [multi_line \ + "Continuing." \ + "\\\[Inferior 1 \\\(process $any\\\) exited normally\\\]"] \ + "continue to exit" + } +} + +foreach_with_prefix fork_func {fork vfork} { + foreach_with_prefix follow {child} { + foreach_with_prefix target-non-stop {auto on off} { + foreach_with_prefix non-stop {off} { + foreach_with_prefix displaced-stepping {auto on off} { + do_test ${fork_func} ${follow} ${target-non-stop} ${non-stop} ${displaced-stepping} + } + } + } + } +} From patchwork Sat Dec 3 21:13:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 61458 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 4C6BF385B1A5 for ; Sat, 3 Dec 2022 21:14:59 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) by sourceware.org (Postfix) with ESMTPS id AD27E3858004 for ; Sat, 3 Dec 2022 21:13:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AD27E3858004 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-f54.google.com with SMTP id f13-20020a1cc90d000000b003d08c4cf679so3228059wmb.5 for ; Sat, 03 Dec 2022 13:13:56 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZfRyy8cEeEiVid/Id+QSVSJT8uacOlR1tQZH+PdbMEM=; b=hYqKwXwyaxe3BmL+iMlgmg/scng1WAb/ICnPRPrLVexBh4WfKc/SoS+5RqQiI5MCE4 kxSLGnaGhbC2LrVJ0MOqyZ1rE8K5GunBmpiznNQSF5RxuLf6ReTJXvytVlfJP8QcArAr h5OGtX+b43auQPIltLPU2qK5GJ5+JjkX8N3xcb079ddTV4j2den87FYdBhY2ePvfB3iX erY8PdUwlrsBWWxpN7CPYyOjWBX4KXRFgaWXY82qAqAX4bd83+nJ25VKqmP9ca2UiKGD 9rE6YVFifDQQ7RPuH2R9s/gZg5De+LSJhN7olzEFjM5L/7IvqwTDb4Euh3qAGqD00OgB b/eQ== X-Gm-Message-State: ANoB5pnZVRMGk8Le8jbv8PpiP7EarqnfcC64YEFNIlwFzeZncwlPPP0o NJFlefa9J5xSNH2TwCmXysN4NOCEtb/lQw== X-Google-Smtp-Source: AA0mqf4j6l9kUto+7juaGoOLHLukc0GgcgH/wveOdQ9uq4SzW05p57/Mv2ELDOfANLCD9jYxnAC3kg== X-Received: by 2002:a05:600c:1e25:b0:3d0:31c9:1d77 with SMTP id ay37-20020a05600c1e2500b003d031c91d77mr39546717wmb.113.1670102035300; Sat, 03 Dec 2022 13:13:55 -0800 (PST) Received: from localhost ([2001:8a0:f912:6700:afd9:8b6d:223f:6170]) by smtp.gmail.com with ESMTPSA id n10-20020adffe0a000000b00241bd7a7165sm10082158wrr.82.2022.12.03.13.13.54 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 03 Dec 2022 13:13:54 -0800 (PST) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 6/6] Remove infrun_thread_thread_exit observer Date: Sat, 3 Dec 2022 21:13:38 +0000 Message-Id: <20221203211338.2264994-7-pedro@palves.net> X-Mailer: git-send-email 2.36.0 In-Reply-To: <20221203211338.2264994-1-pedro@palves.net> References: <20221203211338.2264994-1-pedro@palves.net> MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.29 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 Sender: "Gdb-patches" After the previous patches, I believe this observer isn't necessary anymore for anything. Remove it. Change-Id: Idb33fb6b6f55589c8c523a92169b3ca95a23d0b9 --- gdb/infrun.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gdb/infrun.c b/gdb/infrun.c index f1afc4ba8e2..b24cc6d932d 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3605,14 +3605,6 @@ infrun_thread_stop_requested (ptid_t ptid) } } -static void -infrun_thread_thread_exit (struct thread_info *tp, int silent) -{ - if (target_last_proc_target == tp->inf->process_target () - && target_last_wait_ptid == tp->ptid) - nullify_last_target_wait_ptid (); -} - /* Delete the step resume, single-step and longjmp/exception resume breakpoints of TP. */ @@ -9966,7 +9958,6 @@ enabled by default on some platforms."), "infrun"); gdb::observers::thread_stop_requested.attach (infrun_thread_stop_requested, "infrun"); - gdb::observers::thread_exit.attach (infrun_thread_thread_exit, "infrun"); gdb::observers::inferior_exit.attach (infrun_inferior_exit, "infrun"); gdb::observers::inferior_execd.attach (infrun_inferior_execd, "infrun");