Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 0/3] Adjust a few gdb.threads/ testcases for Cygwin
@ 2026-05-05 12:42 Pedro Alves
  2026-05-05 12:42 ` [PATCH 1/3] Adjust gdb.threads/schedlock.exp " Pedro Alves
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Pedro Alves @ 2026-05-05 12:42 UTC (permalink / raw)
  To: gdb-patches

This mini series adjusts a few gdb.threads/ testcases for Cygwin.  See
individual commit logs.

Pedro Alves (3):
  Adjust gdb.threads/schedlock.exp for Cygwin
  Adjust gdb.threads/multiple-successive-infcall.exp for Cygwin
  Adjust gdb.threads/step-over-trips-on-watchpoint.exp for Cygwin

 .../gdb.threads/multiple-successive-infcall.c |  10 +-
 .../multiple-successive-infcall.exp           | 103 ++++++++++++++----
 gdb/testsuite/gdb.threads/schedlock.exp       |  21 ++++
 .../step-over-trips-on-watchpoint.exp         |  22 +++-
 4 files changed, 130 insertions(+), 26 deletions(-)


base-commit: 297fe552edd546e4fe9f47c7a0765a55ce084f0c
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] Adjust gdb.threads/schedlock.exp for Cygwin
  2026-05-05 12:42 [PATCH 0/3] Adjust a few gdb.threads/ testcases for Cygwin Pedro Alves
@ 2026-05-05 12:42 ` Pedro Alves
  2026-05-05 12:42 ` [PATCH 2/3] Adjust gdb.threads/multiple-successive-infcall.exp " Pedro Alves
  2026-05-05 12:42 ` [PATCH 3/3] Adjust gdb.threads/step-over-trips-on-watchpoint.exp " Pedro Alves
  2 siblings, 0 replies; 4+ messages in thread
From: Pedro Alves @ 2026-05-05 12:42 UTC (permalink / raw)
  To: gdb-patches

This commit adjusts gdb.threads/schedlock.exp to work on Cygwin too.
The main difference to other systems is that on Windows, a Ctrl-C in
the terminal results in Windows injecting a new thread in the inferior
to report a EXCEPTION_DEBUG_EVENT/DBG_CONTROL_C event.  That means
that even with schedlock on, Ctrl-C always switches focus to a
different thread.

With this, gdb.threads/schedlock.exp passes cleanly on Cygwin.

Change-Id: I574c702d370da6eaf92e82ce81efe1a44660b24f
commit-id: f96fcdea
---
 gdb/testsuite/gdb.threads/schedlock.exp | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/gdb/testsuite/gdb.threads/schedlock.exp b/gdb/testsuite/gdb.threads/schedlock.exp
index eeca3f8fd0f..169f6876b62 100644
--- a/gdb/testsuite/gdb.threads/schedlock.exp
+++ b/gdb/testsuite/gdb.threads/schedlock.exp
@@ -105,6 +105,17 @@ proc goto_loop { msg } {
 }
 
 proc my_continue { msg } {
+
+    # On Cygwin, a Ctrl-C in the terminal results in Windows injecting
+    # a new thread in the inferior to report a
+    # EXCEPTION_DEBUG_EVENT/DBG_CONTROL_C event.  That means that even
+    # with schedlock on, Ctrl-C always switches focus to a different
+    # thread.  Hide that fact here by saving/restoring the current
+    # thread.
+    if {[istarget *-*-cygwin*]} {
+	set gdb_thr [get_valueof "" "\$_thread" 0 "save current gdb thread"]
+    }
+
     set test "continue ($msg)"
     gdb_test_multiple "continue" $test {
 	-re "Continuing" {
@@ -114,6 +125,13 @@ proc my_continue { msg } {
 
     stop_process "stop all threads ($msg)"
 
+    # See above.  This must be done before goto_loop, otherwise with
+    # schedlock on, we'd be resuming the injected Ctrl-C thread.
+    if {[istarget *-*-cygwin*]} {
+	gdb_test "thread $gdb_thr" "Switching to thread .*" \
+	    "restore current gdb thread"
+    }
+
     goto_loop $msg
 }
 
@@ -201,6 +219,9 @@ if { $bad == 0 } {
 # before the command was run.  BEFORE_ARGS is the value of the
 # thread's args before the command was run.  LOCKED indicates whether
 # we expect threads other than the selected thread remained locked.
+#
+# Note, on Cygwin, the "we didn't switch threads" test is pointless,
+# see my_continue.
 
 proc check_result { cmd before_thread before_args locked } {
     global NUM
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/3] Adjust gdb.threads/multiple-successive-infcall.exp for Cygwin
  2026-05-05 12:42 [PATCH 0/3] Adjust a few gdb.threads/ testcases for Cygwin Pedro Alves
  2026-05-05 12:42 ` [PATCH 1/3] Adjust gdb.threads/schedlock.exp " Pedro Alves
@ 2026-05-05 12:42 ` Pedro Alves
  2026-05-05 12:42 ` [PATCH 3/3] Adjust gdb.threads/step-over-trips-on-watchpoint.exp " Pedro Alves
  2 siblings, 0 replies; 4+ messages in thread
From: Pedro Alves @ 2026-05-05 12:42 UTC (permalink / raw)
  To: gdb-patches

Running gdb.threads/multiple-successive-infcall.exp on Cygwin results
in a series of cascading timeouts.  There are two problems:

 #1 - Cygwin/Windows start a few threads for their own use.  When you
      reach "main" with "(gdb) start", "info threads" will already
      show more than one thread.  The testcase spawns four threads
      with pthread_create, and it assumes that they get GDB thread ids
      2 through 5.  That is incorrect for Windows.

E.g.:

 (gdb) info threads
   Id   Target Id                                                      Frame
   1    Thread 4104.0x1e60 "multiple-successive-infcall"               0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   2    Thread 4104.0x2490                                             0x00007fff3c450ad4 in ntdll!ZwWaitForWorkViaWorkerFactory ()
    from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   3    Thread 4104.0x2bdc                                             0x00007fff3c450ad4 in ntdll!ZwWaitForWorkViaWorkerFactory ()
    from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   4    Thread 4104.0x1714 "sig"                                       0x00007fff3c44d124 in ntdll!ZwReadFile () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   5    Thread 4104.0x211c "multiple-successive-infcall"               0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   6    Thread 4104.0x2070 "multiple-successive-infcall"               0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
   7    Thread 4104.0x1d3c "multiple-successive-infcall"               0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
 * 8    Thread 4104.0xa54 "multiple-successive-infcall"                thread_function (args=0x10040704c <thread_ids+12>)
     at /cygdrive/c/Users/alves/rocm/gdb/src/gdb/testsuite/gdb.threads/multiple-successive-infcall.c:75

 #2 - The test enables scheduler locking and switches to each thread
      in turn, and then does an infcall.  On Windows, system calls
      aren't interruptible like on Linux.  There's no concept of EINTR
      and syscall restart.  So if a thread is in a syscall, actually
      running kernel code, then an infcall will only complete once the
      syscall returns.  If the syscall is blocked waiting for another
      thread to unblock it, then the infcall never completes.  You can
      pause it with Ctrl-C, but you'll see that the thread hasn't
      executed any user space instruction.

      For example:

       (gdb) t 8
       [Switching to thread 8 (Thread 4104.0xa54)]
       #0  0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
       (gdb) p get_value ()
       * hang *

       * press ctrl-c *

       Thread 8 "multiple-successive-infcall" stopped.
       get_value () at /cygdrive/c/Users/alves/rocm/gdb/src/gdb/testsuite/gdb.threads/multiple-successive-infcall.c:38
       38      get_value ()
       The program being debugged was signaled while in a function called from GDB.
       GDB remains in the frame where the signal was received.
       To change this behavior use "set unwindonsignal on".
       Evaluation of the expression containing the function
       (get_value) will be abandoned.
       When the function is done executing, GDB will silently stop.
       (gdb) bt
       #0  get_value () at /cygdrive/c/Users/alves/rocm/gdb/src/gdb/testsuite/gdb.threads/multiple-successive-infcall.c:38
       #1  <function called from gdb>
       #2  0x00007fff3c44dbb4 in ntdll!ZwWaitForMultipleObjects () from /cygdrive/c/Windows/SYSTEM32/ntdll.dll
       #3  0x00007fff39cd1b40 in WaitForMultipleObjectsEx () from /cygdrive/c/Windows/System32/KERNELBASE.dll
       ...
       (gdb) si
       * hang *

    This results in failures like these:

       call get_value()
       FAIL: gdb.threads/multiple-successive-infcall.exp: thread=4: call inferior function (timeout)

This commit fixes this by adjusting the testcase to make it work on
Cygwin too.  First, it makes the .exp file figure out which threads
are the ones created by the testcase.  The current testcase also tries
the infcall on the main thread.  It's simpler to not worry about the
main thread being blocked in a syscall.  So we just no longer test the
syscall through that thread.  That's OK, because that was not
important for the original motivation for the testcase.

With this, the testcase now passes cleanly on Cygwin.

Change-Id: I5f69bafe6cecb83f18fb22ba7ee2368229fc4f9f
commit-id: 717edd68
---
 .../gdb.threads/multiple-successive-infcall.c |  10 +-
 .../multiple-successive-infcall.exp           | 103 ++++++++++++++----
 2 files changed, 90 insertions(+), 23 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/multiple-successive-infcall.c b/gdb/testsuite/gdb.threads/multiple-successive-infcall.c
index 8e397266dff..aa3ebbd9332 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.c
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.c
@@ -41,8 +41,9 @@ get_value ()
       if (pthread_equal (threads[tid], pthread_self ()))
 	return thread_ids[tid];
     }
-  /* Value for the main thread.  */
-  return 1;
+
+  /* Should not get here.  */
+  return -1;
 }
 
 /* Return the nth Fibonacci number.  */
@@ -93,8 +94,9 @@ main (void)
   printf ("Spawning worker threads\n");
   for (int tid = 0; tid < THREADCOUNT; ++tid)
     {
-      /* Add 2 so the value maps to the debugger's thread identifiers.  */
-      thread_ids[tid] = tid + 2; /* prethreadcreationmarker */
+      /* Add 1 so the value maps to the testcase's thread
+	 identifiers.  */
+      thread_ids[tid] = tid + 1; /* prethreadcreationmarker */
       err = pthread_create (&threads[tid], NULL, thread_function,
 			    (void *) &thread_ids[tid]);
       if (err != 0)
diff --git a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
index 8d438673cf0..7ad841844bb 100644
--- a/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
+++ b/gdb/testsuite/gdb.threads/multiple-successive-infcall.exp
@@ -13,8 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-# multiple-successive-infcall.exp -- Test if GDB can invoke functions on
-# multiple inferiors, one after the other.
+# Test invoking functions on multiple threads, one after the other.
 
 standard_testfile
 
@@ -29,31 +28,97 @@ if {![runto_main]} {
    return 0
 }
 
-# Ensure that each new thread is detected by GDB in the order that the
-# test case creates them, so the thread identifiers match between
-# test and test case.
+# Ensure that each new pthread is spawned one at a time so we can
+# extract its target ID, and not the ID of some auxiliary thread
+# spawned by the runtime.
 gdb_breakpoint [gdb_get_line_number "prethreadcreationmarker"]
 gdb_continue_to_breakpoint "prethreadcreationmarker"
-set after_new_thread_message "created new thread"
-foreach_with_prefix thread {5 4 3}  {
-  gdb_test_multiple "continue" "${after_new_thread_message}" {
-    -re "\\\[New Thread ${hex} \\\(LWP ${::decimal}\\\) \\\(id $decimal\\\)\\\].*${gdb_prompt}" {
-      pass "${after_new_thread_message}"
-    }
-    -re -wrap "\\\[New Thread $decimal\\.$decimal\\\ \\\(id $decimal\\\)]\r\n.*" {
-      pass $gdb_test_name
+set after_new_thread_message "detected new pthread"
+
+# List of the target ids detected.
+set pthread_list {}
+
+# The first 3 pthreads are detected here.
+foreach_with_prefix pthread {1 2 3}  {
+    gdb_test_multiple "continue" "${after_new_thread_message}" {
+	-re -wrap "\\\[New (Thread \[^\r\n\]+) \\\(id $decimal\\\)\\\]\r\n.*" {
+	    set thr $expect_out(1,string)
+	    verbose -log "detected pthread: $thr"
+	    lappend pthread_list $thr
+	    pass $gdb_test_name
+	}
     }
-  }
 }
 
+verbose -log "detected pthread list: $pthread_list"
+
 gdb_breakpoint [gdb_get_line_number "testmarker01"]
-gdb_continue_to_breakpoint "testmarker01"
+
+# Continue to breakpoint.  This detects that last pthread.  It also
+# ensures that no pthread ends up blocked in a syscall, which is
+# important for Windows -- the infcall wouldn't be able to complete
+# until the syscall returns, meaning, the infcall would deadlock.
+with_test_prefix "pthread 4" {
+    gdb_test_multiple "continue" "${after_new_thread_message}" {
+	-re "\\\[New (Thread \[^\r\n\]+) \\\(id $decimal\\\)\\\]\r\n" {
+	    set thr $expect_out(1,string)
+	    verbose -log "detected pthread: $thr"
+	    lappend pthread_list $thr
+	    pass $gdb_test_name
+	}
+    }
+}
+
+# Consume the breakpoint hit and the prompt.
+gdb_test_multiple "" "stop at testmarker01" {
+    -re -wrap "hit Breakpoint .* testmarker01 .*" {
+	pass $gdb_test_name
+    }
+}
+
 gdb_test_no_output "set scheduler-locking on"
 gdb_test "show scheduler-locking" \
   "Mode for locking scheduler during execution is \"on\"."
 
-foreach_with_prefix thread {5 4 3 2 1}  {
-  gdb_test "thread ${thread}" "Switching to .*"
-  gdb_test "call get_value()" "= ${thread}" \
-      "call inferior function"
+set thread_count [get_valueof "" "\$_inferior_thread_count" 0]
+
+# pthread id to be used in test messages in the loop below.
+set testing_pthread 0
+
+for {set thread 1} {$thread <= $thread_count} {incr thread} {
+
+    # 1 if found, 0 if not found, -1 if the test failed.
+    set found -1
+    gdb_test_multiple "thread ${thread}" "extract thread target id" {
+	-re -wrap "Switching to thread $decimal \\((Thread \[^\r\n\]+)\\)\\\]\r\n.*" {
+	    set thr $expect_out(1,string)
+	    verbose -log "extracted: $thr"
+	    if {[lsearch -exact $pthread_list $thr] != -1} {
+		set found 1
+	    } else {
+		set found 0
+	    }
+	}
+    }
+    if {$found == -1} {
+	# gdb_test_multiple already issued a FAIL above.  No point in
+	# continuing.
+	return
+    } elseif {$found == 0} {
+	# Not recognized as a testcase pthread, so it must be a thread
+	# spawned by the runtime or the OS.  Don't use it for testing
+	# the infcall, as the thread may be blocked in a syscall -- on
+	# Windows, the infcall wouldn't be able to complete until the
+	# syscall returns, meaning, the infcall would deadlock.
+	verbose -log "not a known pthread"
+	continue
+    } else {
+	incr testing_pthread
+	with_test_prefix "pthread $testing_pthread" {
+	    gdb_test "call get_value()" "= $testing_pthread" \
+		"call inferior function"
+	}
+    }
 }
+
+gdb_assert {$testing_pthread == 4} "tested all pthreads"
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/3] Adjust gdb.threads/step-over-trips-on-watchpoint.exp for Cygwin
  2026-05-05 12:42 [PATCH 0/3] Adjust a few gdb.threads/ testcases for Cygwin Pedro Alves
  2026-05-05 12:42 ` [PATCH 1/3] Adjust gdb.threads/schedlock.exp " Pedro Alves
  2026-05-05 12:42 ` [PATCH 2/3] Adjust gdb.threads/multiple-successive-infcall.exp " Pedro Alves
@ 2026-05-05 12:42 ` Pedro Alves
  2 siblings, 0 replies; 4+ messages in thread
From: Pedro Alves @ 2026-05-05 12:42 UTC (permalink / raw)
  To: gdb-patches

gdb.threads/step-over-trips-on-watchpoint.exp fails on Cygwin with
many casding timeouts:

 Running /home/alves/rocm/gdb/src/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp ...
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: continue to breakpoint: run to breakpoint in thread 2 (timeout)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: find addresses: clear watch_me (timeout)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: find addresses: watch watch_me (timeout)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: find addresses: continue to watchpoint (timeout)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: find addresses: find addresses (timeout)
 FAIL: gdb.threads/step-over-trips-on-watchpoint.exp: displaced=off: no thread-specific bp: step: find addresses: delete all breakpoints, watchpoints, tracepoints, and catchpoints in delete_breakpoints (timeout)
 ... many more ...

The problem is that the testcase assumes that the program's child
thread is GDB thread ID 2.  This commit removes that assumption.  It
now passes cleanly on Cygwin.

Change-Id: Ief28e6ebf47abdcd2e71c5f2c70caf2d8753ef5e
commit-id: 7207e3c2
---
 .../step-over-trips-on-watchpoint.exp         | 22 ++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
index 0a0c5edb97a..cb87f039c78 100644
--- a/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
+++ b/gdb/testsuite/gdb.threads/step-over-trips-on-watchpoint.exp
@@ -53,6 +53,20 @@ proc do_test { displaced with_bp } {
 		    continue
 		}
 
+		gdb_breakpoint "child_function"
+
+		# Don't assume the testcase's child thread has GDB
+		# thread id 2.  On some systems, like e.g.,
+		# Cygwin/Windows the OS/runtime spawns helper threads
+		# before the child thread is spawned.
+		set thr_child "unknown"
+		gdb_test_multiple "c" "run to child thread" {
+		    -re -wrap "Thread ($::decimal) .*hit Breakpoint .*, child_function.*" {
+			set thr_child $expect_out(1,string)
+			pass $gdb_test_name
+		    }
+		}
+
 		gdb_test_no_output "set displaced-stepping $displaced"
 
 		set line [gdb_get_line_number "set wait-thread breakpoint here"]
@@ -60,15 +74,17 @@ proc do_test { displaced with_bp } {
 		    return
 		}
 		gdb_continue_to_breakpoint "run to wait-thread breakpoint"
-		gdb_test "info threads" "\\\* 1 .*  2 .*" "info threads shows all threads"
+		gdb_test "info threads" "\\\* 1 .*  $thr_child .*" \
+		    "info threads shows all threads"
 
 		gdb_test_no_output "set scheduler-locking on"
 
 		delete_breakpoints
 
 		gdb_breakpoint [gdb_get_line_number "set breakpoint child here"]
-		gdb_test "thread 2" "Switching to .*"
-		gdb_continue_to_breakpoint "run to breakpoint in thread 2"
+		gdb_test "thread $thr_child" "Switching to .*" \
+		    "switch to child thread"
+		gdb_continue_to_breakpoint "run to breakpoint in child thread"
 
 		set address_triggers_watch "<invalid>"
 		set after_address_triggers_watch "<invalid>"
-- 
2.53.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-05-05 12:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-05 12:42 [PATCH 0/3] Adjust a few gdb.threads/ testcases for Cygwin Pedro Alves
2026-05-05 12:42 ` [PATCH 1/3] Adjust gdb.threads/schedlock.exp " Pedro Alves
2026-05-05 12:42 ` [PATCH 2/3] Adjust gdb.threads/multiple-successive-infcall.exp " Pedro Alves
2026-05-05 12:42 ` [PATCH 3/3] Adjust gdb.threads/step-over-trips-on-watchpoint.exp " Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox