[PATCH v4 1/3] gdb/testsuite: add test for run/attach while program is running
Simon Marchi
simon.marchi@polymtl.ca
Mon Jan 25 04:57:28 GMT 2021
A previous version of this patch series broke the use case of doing
"run" or "attach" while the program is running, but it wasn't caught by
the testsuite, which means it's not covered. Add a test for that.
gdb/testsuite/ChangeLog:
* gdb.base/run-attach-while-running.exp: New.
* gdb.base/run-attach-while-running.c: New.
Change-Id: I77f098ec0b28dc2d4575ea80e941f6a75273e431
---
.../gdb.base/run-attach-while-running.c | 69 +++++++++
.../gdb.base/run-attach-while-running.exp | 131 ++++++++++++++++++
2 files changed, 200 insertions(+)
create mode 100644 gdb/testsuite/gdb.base/run-attach-while-running.c
create mode 100644 gdb/testsuite/gdb.base/run-attach-while-running.exp
diff --git a/gdb/testsuite/gdb.base/run-attach-while-running.c b/gdb/testsuite/gdb.base/run-attach-while-running.c
new file mode 100644
index 000000000000..57bebbe6456e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/run-attach-while-running.c
@@ -0,0 +1,69 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+#include <assert.h>
+
+#ifndef WITH_THREADS
+# error "WITH_THREADS must be defined."
+#endif
+
+#if WITH_THREADS
+# include <pthread.h>
+
+static pthread_barrier_t barrier;
+
+static void *
+thread_func (void *p)
+{
+ pthread_barrier_wait (&barrier);
+
+ for (int i = 0; i < 30; i++)
+ sleep (1);
+
+ return NULL;
+}
+
+#endif /* WITH_THREADS */
+
+static void
+all_started (void)
+{}
+
+int
+main (void)
+{
+ alarm (30);
+
+#if WITH_THREADS
+ int ret = pthread_barrier_init (&barrier, NULL, 2);
+ assert (ret == 0);
+
+ pthread_t thread;
+ ret = pthread_create (&thread, NULL, thread_func, NULL);
+ assert (ret == 0);
+
+ pthread_barrier_wait (&barrier);
+#endif /* WITH_THREADS */
+
+ all_started ();
+
+ for (int i = 0; i < 30; i++)
+ sleep (1);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/run-attach-while-running.exp b/gdb/testsuite/gdb.base/run-attach-while-running.exp
new file mode 100644
index 000000000000..385bbc410dbf
--- /dev/null
+++ b/gdb/testsuite/gdb.base/run-attach-while-running.exp
@@ -0,0 +1,131 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+# Test doing a "run" or an "attach" while the program is running.
+#
+# We test a non-threaded and a threaded configuration, so that targets that
+# don't support threads get some testing, but we also test with threads when
+# possible in case that triggers some multi-thread-specific bugs.
+
+standard_testfile
+
+set binfile_threads ${binfile}-threads
+set binfile_nothreads ${binfile}-nothreads
+unset binfile
+
+# Valid parameter / axis values:
+#
+# - non-stop: "off" of "on"
+# - threaded: 0 or 1
+# - run-or-attach: "run" or "attach"
+
+proc_with_prefix test { non-stop threaded run-or-attach } {
+ if { ${run-or-attach} == "attach" && ![can_spawn_for_attach] } {
+ unsupported "attach not supported"
+ return
+ }
+
+ # Choose the right (threaded or not) binfile.
+ if { $threaded } {
+ set binfile $::binfile_threads
+ } else {
+ set binfile $::binfile_nothreads
+ }
+
+ save_vars ::GDBFLAGS {
+ set ::GDBFLAGS "$::GDBFLAGS -ex \"set non-stop ${non-stop}\""
+
+ # The test doesn't work when the remote target uses the synchronous
+ # remote protocol, because GDB can't kill the remote inferior while it
+ # is running, when we "run" or "attach" again. When aswering "yes" to
+ # the "Start it from the beginning?" question, we otherwise get:
+ #
+ # Cannot execute this command while the target is running. Use the
+ # "interrupt" command to stop the target and then try again.
+ #
+ # Interrupting the target would defeat the purpose of the test. So
+ # when non-stop is off and using the remote target, force the target
+ # to use the async / non-stop version of the protocol.
+ if { [target_info exists gdb_protocol] && ${non-stop} == "off" } {
+ set ::GDBFLAGS "$::GDBFLAGS -ex \"maint set target-non-stop on\""
+ }
+
+ clean_restart $binfile
+ }
+
+ if { ![runto_main] } {
+ untested "could not run to main"
+ return
+ }
+
+ gdb_breakpoint "all_started" "temporary"
+ gdb_continue_to_breakpoint "continue to all_started"
+
+ # If all-stop, everything stopped when we hit the all_started breakpoint,
+ # so resume execution in background. If running the non-threaded version,
+ # our only thread is stopped in any case, so resume as well. But if we are
+ # in non-stop with two threads, we have one running and one stopped, leave
+ # it like this, it makes an interesting test case.
+ if { ${non-stop} == "off" || !${threaded} } {
+ gdb_test "continue &" "Continuing."
+ }
+
+ gdb_test_no_output "set confirm off"
+
+ # Run again (or, connect to a new stub if using a stub), take advantage
+ # of the fact that runto_main leaves the breakpoint on main in place.
+ if { ${run-or-attach} == "run" } {
+ gdb_run_cmd
+ gdb_test "" "Breakpoint $::decimal, .*main.*" "hit main breakpoint after re-run"
+ } elseif { ${run-or-attach} == "attach" } {
+ set test_spawn_id [spawn_wait_for_attach $binfile]
+ set test_pid [spawn_id_get_pid $test_spawn_id]
+
+ gdb_test "attach $test_pid" "Attaching to program: .*" "attach to process"
+
+ gdb_exit
+ kill_wait_spawned_process $test_spawn_id
+ } else {
+ error "Invalid value for run-or-attach"
+ }
+}
+
+# Build and test with the non-threaded version.
+if { [build_executable "failed to prepare" ${binfile_nothreads} ${srcfile} \
+ {debug additional_flags=-DWITH_THREADS=0} ] } {
+ return
+}
+
+with_test_prefix {threaded=0} {
+ foreach_with_prefix run-or-attach {run attach} {
+ foreach_with_prefix non-stop {off on} {
+ test ${non-stop} 0 ${run-or-attach}
+ }
+ }
+}
+
+# Build and test with the threaded version.
+if { [build_executable "failed to prepare" ${binfile_threads} ${srcfile} \
+ {debug pthreads additional_flags=-DWITH_THREADS=1} ] } {
+ return
+}
+
+with_test_prefix {threaded=1} {
+ foreach_with_prefix run-or-attach {run attach} {
+ foreach_with_prefix non-stop {off on} {
+ test ${non-stop} 1 ${run-or-attach}
+ }
+ }
+}
--
2.30.0
More information about the Gdb-patches
mailing list