* [PATCH 0/5] Fix a few Cygwin/MinGW problems
@ 2026-05-22 0:16 Pedro Alves
2026-05-22 0:16 ` [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1 Pedro Alves
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
I tried to make gdb.python/py-events.exp work on Cygwin, which, as
usual, revealed a few other problems...
- "set cwd ..." does not work properly on Cygwin, the program does not
even start up with that -- affects both GDB and GDBserver.
- gdb.base/exitsignal.exp needs adjustment for Cygwin.
- The inferior exit code / termination signal is mishandled on Windows.
- gdb.python/py-events.exp needs a lot of adjustment for Cygwin and MinGW.
gdb.base/exitsignal.exp and gdb.python/py-events.exp both tested on
x86_64-unknown-linux-gnu and on Cygwin.
All fixed by this series.
Pedro Alves (5):
Fix "set cwd ..." on Cygwin, part 1
Fix "set cwd ..." on Cygwin, part 2
Adjust gdb.base/exitsignal.exp for Cygwin
Fix exit/signal code on Cygwin
Adjust gdb.python/py-events.exp for Cygwin/MinGW
gdb/nat/windows-nat.c | 42 +++++++++++++++
gdb/nat/windows-nat.h | 4 ++
gdb/testsuite/gdb.base/exitsignal.exp | 8 ++-
gdb/testsuite/gdb.python/py-events.c | 3 --
gdb/testsuite/gdb.python/py-events.exp | 73 ++++++++++++++------------
gdb/windows-nat.c | 28 ++++------
gdbserver/win32-low.cc | 43 +++++++++------
7 files changed, 130 insertions(+), 71 deletions(-)
base-commit: f6c1ca239d932db39a6f19d9bd343f4f4fddba76
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
@ 2026-05-22 0:16 ` Pedro Alves
2026-05-22 13:54 ` Tom Tromey
2026-05-22 0:16 ` [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2 Pedro Alves
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
When running gdb.base/exitsignal.exp on Cygwin, we see:
(gdb) set cwd /cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal
(gdb) run
Starting program: /cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal/exitsignal
Error converting inferior cwd: 28
(gdb) FAIL: gdb.base/exitsignal.exp: runto: run to main
28 is ENOSPC. But this isn't really literally no space left, though.
cygwin_conv_path documentation mentions that error code.
According to the Cygwin API documentation for cygwin_conv_path, the
function fails with ENOSPC ("No space left on device") when the size
of the destination buffer is smaller than what is required for the
conversion. See:
https://cygwin.com/cygwin-api/func-cygwin-conv-path.html
If we look closely at how the buffer size argument is being passed, we
see we have two problems here:
1) Incorrectly passing down the input buffer size instead of the
output size.
The code passes strlen(inferior_cwd) as the size of the destination
buffer (infcwd). However, the target Windows path format
(e.g. "D:\cygwin-gdb\..." in my case) could be longer or shorter than
the POSIX source path ("/cygdrive/d/..."). In my specific case, the
source string is 64 characters, while the target Windows string is 61
(wide) characters (and twice as many bytes).
2) Incorrectly passing character count instead of byte count
The conversion target token is CCP_POSIX_TO_WIN_W. The _W means that
the destination buffer infcwd takes wide characters (wchar_t). The
documentation states that the size argument is in bytes, not
characters.
This commit fixes it, by passing the byte size of the destination
buffer.
Change-Id: I70af6ef394f48da35ccc2e04ef764915e09e59de
commit-id: 66c930c2
---
gdb/windows-nat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index d506b42fbda..862568fa21e 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2925,7 +2925,7 @@ windows_nat_target::create_inferior (const char *exec_file,
if (inferior_cwd != NULL
&& cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
- infcwd, strlen (inferior_cwd)) < 0)
+ infcwd, sizeof (infcwd)) < 0)
error (_("Error converting inferior cwd: %d"), errno);
args = (wchar_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
2026-05-22 0:16 ` [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1 Pedro Alves
@ 2026-05-22 0:16 ` Pedro Alves
2026-05-22 14:37 ` Tom Tromey
2026-05-22 0:16 ` [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin Pedro Alves
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
Even after the previous patch, on both native and gdbserver Cygwin, we
get:
(gdb) set cwd /cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal
(gdb) start
Temporary breakpoint 3 at 0x100401094: file /home/alves/rocm/gdb/src/gdb/testsuite/gdb.base/segv.c, line 26.
Starting program: /cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal/exitsignal.exe
❌️ Error creating process /cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal/exitsignal.exe (error 6): The handle is invalid.
(gdb)
On the native side, this is because in
windows_nat_target::create_inferior, we unconditionally convert
forward slashes to backward slashes:
/cygdrive/d/cygwin-gdb/build-testsuite/outputs/gdb.base/exitsignal
=>
\cygdrive\d\cygwin-gdb\build-testsuite\outputs\gdb.base\exitsignal
and then cygwin_conv_path(CCP_POSIX_TO_WIN_W) does nothing on such
path, as the backward slashes make the path not look like a Unix-style
path.
CreateProcess then fails to CD into that directory, as that's not a
real Windows native path.
The fix is to not do the slashes replacement on Cygwin.
On the gdbserver side, we're just completely missing the
cygwin_conv_path logic. This commit adds it. The code isn't shared
with GDB because GDB uses wide chars, and gdbserver uses narrow char.
Change-Id: I004f2a562757a566423f6acb9aecfcc1a7f2f746
commit-id: 85aa8c22
---
gdb/windows-nat.c | 14 ++++++++------
gdbserver/win32-low.cc | 30 +++++++++++++++++++++++++-----
2 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index 862568fa21e..a284438bd36 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -2881,10 +2881,17 @@ windows_nat_target::create_inferior (const char *exec_file,
else
{
expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+ inferior_cwd = expanded_infcwd.c_str ();
+#ifndef __CYGWIN__
/* Mirror slashes on inferior's cwd. */
std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
'/', '\\');
- inferior_cwd = expanded_infcwd.c_str ();
+#else
+ if (cygwin_conv_path (CCP_POSIX_TO_WIN_W,
+ inferior_cwd,
+ infcwd, sizeof (infcwd)) < 0)
+ error (_("Error converting inferior cwd: %d"), errno);
+#endif
}
memset (&si, 0, sizeof (si));
@@ -2923,11 +2930,6 @@ windows_nat_target::create_inferior (const char *exec_file,
flags |= DEBUG_PROCESS;
}
- if (inferior_cwd != NULL
- && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
- infcwd, sizeof (infcwd)) < 0)
- error (_("Error converting inferior cwd: %d"), errno);
-
args = (wchar_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
* sizeof (wchar_t));
wcscpy (args, toexec);
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 469ff32f070..6f1cf5ed025 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -448,9 +448,11 @@ static BOOL
create_process (const char *program, char *args,
DWORD flags, PROCESS_INFORMATION *pi)
{
- const std::string &inferior_cwd = get_inferior_cwd ();
BOOL ret;
size_t argslen, proglen;
+#ifdef __CYGWIN__
+ char infcwd_buf[PATH_MAX];
+#endif
proglen = strlen (program) + 1;
argslen = strlen (args) + proglen;
@@ -458,6 +460,27 @@ create_process (const char *program, char *args,
STARTUPINFOA si = { sizeof (STARTUPINFOA) };
char *program_and_args = (char *) alloca (argslen + 1);
+ const char *inferior_cwd = get_inferior_cwd ().c_str ();
+ std::string expanded_infcwd;
+ if (*inferior_cwd == '\0')
+ inferior_cwd = nullptr;
+ else
+ {
+ expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+ inferior_cwd = expanded_infcwd.c_str ();
+#ifndef __CYGWIN__
+ /* Mirror slashes on inferior's cwd. */
+ std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+ '/', '\\');
+#else
+ if (cygwin_conv_path (CCP_POSIX_TO_WIN_A,
+ inferior_cwd,
+ infcwd_buf, sizeof (infcwd_buf)) < 0)
+ error (_("Error converting inferior cwd: %d"), errno);
+ inferior_cwd = infcwd_buf;
+#endif
+ }
+
strcpy (program_and_args, program);
strcat (program_and_args, " ");
strcat (program_and_args, args);
@@ -465,10 +488,7 @@ create_process (const char *program, char *args,
program_and_args, /* command line */
flags, /* start flags */
NULL, /* environment */
- /* current directory */
- (inferior_cwd.empty ()
- ? NULL
- : gdb_tilde_expand (inferior_cwd).c_str()),
+ inferior_cwd, /* current directory */
get_client_state ().disable_randomization,
&si, /* start info */
pi); /* proc info */
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
2026-05-22 0:16 ` [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1 Pedro Alves
2026-05-22 0:16 ` [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2 Pedro Alves
@ 2026-05-22 0:16 ` Pedro Alves
2026-05-22 15:09 ` Tom Tromey
2026-05-22 0:16 ` [PATCH 4/5] Fix exit/signal code on Cygwin Pedro Alves
2026-05-22 0:16 ` [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW Pedro Alves
4 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
Cygwin has this feature where if the program is about to die with a
signal, and there's a debugger attached, it raises a SIGTRAP via
DebugBreak. So if you try to pass a terminating signal to the
inferior, you see that SIGTRAP first, before the process exits with
the signal. E.g.:
Thread 1 "segfault" received signal SIGSEGV, Segmentation fault.
0x0000000100401092 in main () at segfault.cc:5
5 *(volatile int *)0;
(gdb) c
Continuing.
Thread 1 "segfault" received signal SIGTRAP, Trace/breakpoint trap.
0x00007ffe99d35a13 in KERNELBASE!DebugBreak () from C:/WINDOWS/System32/KERNELBASE.dll
(gdb) bt
#0 0x00007ffe99d35a13 in KERNELBASE!DebugBreak () from C:/WINDOWS/System32/KERNELBASE.dll
#1 0x00007ffe896163b7 in break_here () at /usr/src/debug/cygwin-3.6.9-1/winsup/cygwin/dcrt0.cc:473
#2 0x00007ffe8962fe13 in try_to_debug () at /usr/src/debug/cygwin-3.6.9-1/winsup/cygwin/exceptions.cc:599
#3 exception::handle (e=0x7ffffc9b0, frame=<optimized out>, in=0x7ffffc4c0, dispatch=<optimized out>) at /usr/src/debug/cygwin-3.6.9-1/winsup/cygwin/exceptions.cc:812
#4 0x00007ffe9c5e63df in ntdll!.chkstk () from C:/WINDOWS/SYSTEM32/ntdll.dll
#5 0x00007ffe9c499497 in ntdll!RtlLocateExtendedFeature () from C:/WINDOWS/SYSTEM32/ntdll.dll
#6 0x00007ffe9c5e5d1e in ntdll!KiUserExceptionDispatcher () from C:/WINDOWS/SYSTEM32/ntdll.dll
#7 0x0000000100401092 in main () at segfault.cc:5
(gdb) c
Continuing.
...
[Inferior 1 (process 8032) exited with code 05400]
(gdb)
gdb.base/exitsignal.exp fails on Cygwin partly because it doesn't take
that into account. This commit fixes it.
In addition, the typical adjustement for the fact that all programs
are multi-threaded on Cygwin is also necessary.
gdb.base/exitsignal.exp still won't pass cleanly yet. That'll be
finally fixed in the next patch.
Change-Id: I2d18e2604afe3a4f80987848e2c1cd307ed43401
commit-id: 013964ce
---
gdb/testsuite/gdb.base/exitsignal.exp | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/gdb/testsuite/gdb.base/exitsignal.exp b/gdb/testsuite/gdb.base/exitsignal.exp
index aa2710450b5..f1effcd8cea 100644
--- a/gdb/testsuite/gdb.base/exitsignal.exp
+++ b/gdb/testsuite/gdb.base/exitsignal.exp
@@ -50,7 +50,13 @@ gdb_test "print \$_exitcode" " = void" \
"\$_exitcode is void before running"
# Trigger SIGSEGV.
-gdb_test "continue" "Program received signal SIGSEGV.*" "trigger SIGSEGV"
+gdb_test "continue" "(Thread .*|Program) received signal SIGSEGV.*" "trigger SIGSEGV"
+
+if {[istarget "*-*-cygwin*"]} {
+ # Cygwin calls DebugBreak before it lets the process exit.
+ gdb_test "continue" "Thread .* received signal SIGTRAP.*" \
+ "trigger try_to_debug SIGTRAP"
+}
# Continue until the end.
gdb_test "continue" "Program terminated with signal SIGSEGV.*" \
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 4/5] Fix exit/signal code on Cygwin
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
` (2 preceding siblings ...)
2026-05-22 0:16 ` [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin Pedro Alves
@ 2026-05-22 0:16 ` Pedro Alves
2026-05-22 7:15 ` Eli Zaretskii
2026-05-22 0:16 ` [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW Pedro Alves
4 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
I noticed that on native Cygwin, gdb.python/py-events.exp has this:
[Thread 15952.0x534 (id 1) exited with code 12]
...
Program terminated with signal SIGSYS, Bad system call.
...
(gdb) FAIL: gdb.python/py-events.exp: Inferior 1 terminated.
The program exits with normal exit code 12, not a signal. SIGSYS is
12.
Similarly, gdb.base/exitsignal.exp has this:
continue
Continuing.
[Thread 15220.0x219c (id 1) exited with code 2816]
[Thread 15220.0x3a50 (id 3) exited with code 2816]
[Thread 15220.0x25a0 (id 4) exited with code 2816]
[Inferior 1 (process 15220) exited with code 05400]
(gdb) FAIL: gdb.base/exitsignal.exp: program terminated with SIGSEGV (the program exited)
Here, the program exits with SIGSEGV, not normal exit code 2816 (05400
in octal).
The problem is that gdb/windows-nat.c does not know about Cygwin's
exit codes as seen from the native Windows side. Same for gdbserver's
win32-low.c.
This commit fixes it. To avoid duplicating code, it adds a new
native_exit_code_to_target_status function in nat/windows-nat.c used
by both GDB and GDBserver, with the MinGW-specific logic added by
commit 559e7e5056 ("Improve process exit status macros on MinGW")
moved there too.
Change-Id: I5c4d9cd81209d46598575518ef2fd205d77f9b66
commit-id: 153617c2
---
gdb/nat/windows-nat.c | 42 ++++++++++++++++++++++++++++++++++++++++++
gdb/nat/windows-nat.h | 4 ++++
gdb/windows-nat.c | 14 ++------------
gdbserver/win32-low.cc | 13 ++-----------
4 files changed, 50 insertions(+), 23 deletions(-)
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index b093acda342..4c8c9ea32a8 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -18,6 +18,8 @@
#include "nat/windows-nat.h"
#include "gdbsupport/common-debug.h"
+#include "gdbsupport/gdb_signals.h"
+#include "gdbsupport/gdb_wait.h"
#include "target/target.h"
#undef GetModuleFileNameEx
@@ -694,6 +696,46 @@ windows_process_info::add_all_dlls ()
/* See nat/windows-nat.h. */
+target_waitstatus
+native_exit_code_to_target_status (DWORD exit_code)
+{
+ target_waitstatus tstatus;
+
+#ifdef __CYGWIN__
+ /* /usr/include/cygwin/wait.h explains that a wait status is 16
+ bits, and looks like:
+
+ "<1 byte info> <1 byte code>
+ <code> == 0, child has exited, info is the exit value
+ <code> == 1..7e, child has exited, code is the signal number.
+ <code> == 7f, child has stopped, info was the signal number.
+ <code> == 80, there was a core dump."
+
+ However, when passing the wait status to native ExitProcess as a
+ native exit code, cygwin1.dll swaps the <info>/<code> bytes.
+ Swap them back into a wait status here. */
+ int wstatus = ((exit_code & 0xff) << 8) | ((exit_code >> 8) & 0xff);
+ if (!WIFSIGNALED (wstatus))
+ tstatus.set_exited (WEXITSTATUS (wstatus));
+ else
+ tstatus.set_signalled (gdb_signal_from_host (WTERMSIG (wstatus)));
+#else
+ /* If the exit status looks like a fatal exception, but we don't
+ recognize the exception's code, make the original exit status
+ value available, to avoid losing information. */
+ int exit_signal
+ = WIFSIGNALED (exit_code) ? WTERMSIG (exit_code) : -1;
+ if (exit_signal == -1)
+ tstatus.set_exited (exit_code);
+ else
+ tstatus.set_signalled (gdb_signal_from_host (exit_signal));
+#endif
+
+ return tstatus;
+}
+
+/* See nat/windows-nat.h. */
+
std::string
event_code_to_string (DWORD event_code)
{
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index 52378765438..1cabe288cee 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -347,6 +347,10 @@ struct windows_process_info
int get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len);
};
+/* Convert a native ExitProcess exit code to a target wait status. */
+
+extern target_waitstatus native_exit_code_to_target_status (DWORD exit_code);
+
/* Return a string version of EVENT_CODE. */
extern std::string event_code_to_string (DWORD event_code);
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index a284438bd36..54755a4c996 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -62,7 +62,6 @@
#include "complaints.h"
#include "gdbsupport/gdb_tilde_expand.h"
#include "gdbsupport/pathstuff.h"
-#include "gdbsupport/gdb_wait.h"
#include "gdbsupport/symbol.h"
#include "inf-loop.h"
@@ -1610,17 +1609,8 @@ windows_nat_target::get_windows_debug_event
}
else if (windows_process->saw_create == 1)
{
- DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
- /* If the exit status looks like a fatal exception, but we
- don't recognize the exception's code, make the original
- exit status value available, to avoid losing
- information. */
- int exit_signal
- = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
- if (exit_signal == -1)
- ourstatus->set_exited (exit_status);
- else
- ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
+ DWORD exit_code = current_event->u.ExitProcess.dwExitCode;
+ *ourstatus = native_exit_code_to_target_status (exit_code);
thread_id = current_event->dwThreadId;
diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc
index 6f1cf5ed025..23812c0689f 100644
--- a/gdbserver/win32-low.cc
+++ b/gdbserver/win32-low.cc
@@ -33,7 +33,6 @@
#include <process.h>
#include "gdbsupport/gdb_tilde_expand.h"
#include "gdbsupport/common-inferior.h"
-#include "gdbsupport/gdb_wait.h"
using namespace windows_nat;
@@ -1062,16 +1061,8 @@ get_child_debug_event (DWORD *continue_status,
case EXIT_PROCESS_DEBUG_EVENT:
{
- DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
- /* If the exit status looks like a fatal exception, but we
- don't recognize the exception's code, make the original
- exit status value available, to avoid losing information. */
- int exit_signal
- = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
- if (exit_signal == -1)
- ourstatus->set_exited (exit_status);
- else
- ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
+ DWORD exit_code = current_event->u.ExitProcess.dwExitCode;
+ *ourstatus = native_exit_code_to_target_status (exit_code);
}
continue_last_debug_event (DBG_CONTINUE, debug_threads);
break;
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
` (3 preceding siblings ...)
2026-05-22 0:16 ` [PATCH 4/5] Fix exit/signal code on Cygwin Pedro Alves
@ 2026-05-22 0:16 ` Pedro Alves
2026-05-22 7:18 ` Eli Zaretskii
4 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2026-05-22 0:16 UTC (permalink / raw)
To: gdb-patches
This commit fixes several issues in gdb.python/py-events.exp for
Cygwin and MinGW. With these fixed, the testcase passes cleanly on
Cygwin. I haven't tested on MinGW, but at least the test should be
able to compile & run there now.
1) - GDB prints Windows thread IDs in hex:
(gdb) thread
[Current thread is 1 (Thread 9528.0xa9c)]
The corrent code assume decimal, so we only (incorrectly) extract the
"0" after the dot.
2) - Thread and process ID number spaces are different.
The current code assumes that the extract thread is is the same number
as the extracted process id, which is not true on Windows.
3) - there is no "info proc" command on Windows
The testcase is using "info proc" to extract the inferior's process
it. But "info proc" does not exist on all targets, including Windows.
Switch to using "inferior" instead.
4) - The testcase uses fork, and relies on "set detach-on-fork off"
There is fork on Cygwin, but GDB can't follow forks there, so
"detach-on-fork off" has no effect. And also, there is no fork on
native Windows, which makes the testcase unusable on MinGW currently.
I don't see any reason the testcase needs to use fork or multiple
inferiors:
- To test the clear_objfiles event, test a more directed "file"
command instead of testing that following a fork emits it.
- There's a test that quits gdb while some inferiors are being
debugged, and it test that GDB emits gdb.ExitedEvent with no
'exit_code' attribute. Quitting while an inferior is being
debugged makes GDB kill the inferior. So what that is really being
tested is that killing an inferior emits such an event. So write
such an explicit test.
Also tested on x86_64-unknown-linux-gnu.
Change-Id: I21ee8af7b52653c6fdff9b4c1596cdde3cfe751a
commit-id: de2bf164
---
gdb/testsuite/gdb.python/py-events.c | 3 --
gdb/testsuite/gdb.python/py-events.exp | 73 ++++++++++++++------------
2 files changed, 40 insertions(+), 36 deletions(-)
diff --git a/gdb/testsuite/gdb.python/py-events.c b/gdb/testsuite/gdb.python/py-events.c
index b1910f75ed9..6a0b407042a 100644
--- a/gdb/testsuite/gdb.python/py-events.c
+++ b/gdb/testsuite/gdb.python/py-events.c
@@ -15,12 +15,9 @@
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>
-
extern void do_nothing (void);
int second(){
- fork() ;
return 12;
}
diff --git a/gdb/testsuite/gdb.python/py-events.exp b/gdb/testsuite/gdb.python/py-events.exp
index 16a290c31c2..5a40ee4ac97 100644
--- a/gdb/testsuite/gdb.python/py-events.exp
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -45,8 +45,6 @@ gdb_breakpoint "main" {temporary}
gdb_test "run" ".*event type: new_objfile.*new objfile name.*" "new objfile notification"
-gdb_test_no_output "set detach-on-fork off" ""
-
gdb_test "test-events" "Event testers registered."
gdb_breakpoint "first"
@@ -76,17 +74,23 @@ delete_breakpoints
# Test inferior call events
set process_id "invalid"
+set thread_id "invalid"
gdb_test_multiple "thread" "get current thread" {
-re -wrap "process ($decimal).*" {
set process_id $expect_out(1,string)
+ set thread_id $process_id
pass $gdb_test_name
}
-re -wrap "Thread $hex \\(LWP ($decimal)\\).*" {
set process_id $expect_out(1,string)
+ set thread_id $process_id
pass $gdb_test_name
}
- -re -wrap "Thread $decimal\.($decimal).*" {
+ -re -wrap "Thread ($decimal)\.($hex|$decimal).*" {
set process_id $expect_out(1,string)
+ set thread_id $expect_out(2,string)
+ # Convert from hex to decimal.
+ set thread_id [expr {$thread_id}]
pass $gdb_test_name
}
}
@@ -99,9 +103,9 @@ gdb_test_multiple "print do_nothing" "get address of do_nothing" {
}
set expected [list "event type: pre-call"]
-lappend expected "ptid: \\($process_id, $process_id, 0\\)" "address: $addr"
+lappend expected "ptid: \\($process_id, $thread_id, 0\\)" "address: $addr"
lappend expected "event type: post-call"
-lappend expected "ptid: \\($process_id, $process_id, 0\\)" "address: $addr"
+lappend expected "ptid: \\($process_id, $thread_id, 0\\)" "address: $addr"
gdb_test_sequence "call do_nothing()" "" $expected
# Test register changed event
@@ -202,7 +206,7 @@ gdb_test_no_output "delete $second_breakpoint"
#test exited event.
proc get_process_id {test} {
global gdb_prompt
- gdb_test_multiple "info proc" $test {
+ gdb_test_multiple "inferior" $test {
-re "process (\\d+).*$gdb_prompt $" {
set process_id $expect_out(1,string)
pass $gdb_test_name
@@ -211,24 +215,13 @@ proc get_process_id {test} {
return ${process_id}
}
-set process_id [get_process_id "get inferior 1 process id"]
+set process_id [get_process_id "get inferior process id"]
gdb_test "continue" ".*event type: continue.*
-.*clear_objfiles\[\r\n\]*progspace: .*py-events.*
.*event type: exit.*
.*exit code: 12.*
.*exit inf: 1.*
.*exit pid: $process_id.*
-dir ok: True.*" "Inferior 1 terminated."
-
-gdb_test "inferior 2" ".*Switching to inferior 2.*"
-set process_id [get_process_id "get inferior 2 process id"]
-gdb_test "continue" ".*event type: continue.*
-.*event type: exit.*
-.*exit code: 12.*
-.*exit inf: 2.*
-.*exit pid: $process_id.*
-dir ok: True.*" "Inferior 2 terminated."
-
+dir ok: True.*" "inferior terminated"
# Test before_prompt event.
gdb_test_multiline "define new user command" \
@@ -280,29 +273,30 @@ with_test_prefix "inferior continue exit" {
gdb_test "print \$_foo" "= 2" "check foo after start continue"
}
-# Check that when GDB exits, we see gdb.ExitedEvent objects with no
-# 'exit_code' attribute, and that a gdb.GdbExitingEvent is emitted.
-with_test_prefix "gdb exiting: normal" {
+# Check that when GDB kills an inferior, we see gdb.ExitedEvent
+# objects with no 'exit_code' attribute.
+with_test_prefix "kill inferior" {
+ if {![runto_main]} {
+ return
+ }
gdb_test "test-exiting-event normal" "GDB exiting event registered\\."
+ gdb_test "with confirm off -- kill" \
+ "event type: exit\r\nexit code: not-present\r\nexit inf: $decimal\r\nexit pid: $decimal\r\ndir ok: False\r\n.*" \
+ "exit code not present"
+}
+
+# Check that when GDB exits, we see that a gdb.GdbExitingEvent is
+# emitted.
+with_test_prefix "gdb exiting: normal" {
set saw_exiting_event 0
- set saw_inferior_exit 0
- gdb_test_multiple "quit" "" {
- -re "Quit anyway\\? \\(y or n\\) $" {
- send_gdb "y\n"
- exp_continue
- }
+ gdb_test_multiple "with confirm off -- quit" "quit" {
-re "event type: gdb-exiting\r\nexit code: $decimal" {
incr saw_exiting_event
exp_continue
}
- -re "event type: exit\r\nexit code: not-present\r\nexit inf: $decimal\r\nexit pid: $decimal\r\ndir ok: False\r\n" {
- incr saw_inferior_exit
- exp_continue
- }
eof {
gdb_assert { $saw_exiting_event == 1 }
- gdb_assert { $saw_inferior_exit == 2 }
pass $gdb_test_name
}
}
@@ -348,3 +342,16 @@ with_test_prefix "gdb exiting: error" {
}
}
}
+
+# Test clear_objfiles event.
+
+with_test_prefix "clear_objfiles" {
+ clean_restart ${testfile}
+
+ gdb_test_no_output "source ${pyfile}" "load python file"
+ gdb_test "test-objfile-events" "Object file events registered."
+
+ gdb_test "with confirm off -- file" \
+ "event type: clear_objfiles\r\nprogspace: None\r\n.*" \
+ "file cleared"
+}
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 4/5] Fix exit/signal code on Cygwin
2026-05-22 0:16 ` [PATCH 4/5] Fix exit/signal code on Cygwin Pedro Alves
@ 2026-05-22 7:15 ` Eli Zaretskii
2026-05-25 16:47 ` Pedro Alves
0 siblings, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2026-05-22 7:15 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> From: Pedro Alves <pedro@palves.net>
> Date: Fri, 22 May 2026 01:16:25 +0100
>
> I noticed that on native Cygwin, gdb.python/py-events.exp has this:
>
> [Thread 15952.0x534 (id 1) exited with code 12]
> ...
> Program terminated with signal SIGSYS, Bad system call.
> ...
> (gdb) FAIL: gdb.python/py-events.exp: Inferior 1 terminated.
>
> The program exits with normal exit code 12, not a signal. SIGSYS is
> 12.
>
> Similarly, gdb.base/exitsignal.exp has this:
>
> continue
> Continuing.
> [Thread 15220.0x219c (id 1) exited with code 2816]
> [Thread 15220.0x3a50 (id 3) exited with code 2816]
> [Thread 15220.0x25a0 (id 4) exited with code 2816]
> [Inferior 1 (process 15220) exited with code 05400]
> (gdb) FAIL: gdb.base/exitsignal.exp: program terminated with SIGSEGV (the program exited)
>
> Here, the program exits with SIGSEGV, not normal exit code 2816 (05400
> in octal).
>
> The problem is that gdb/windows-nat.c does not know about Cygwin's
> exit codes as seen from the native Windows side. Same for gdbserver's
> win32-low.c.
>
> This commit fixes it. To avoid duplicating code, it adds a new
> native_exit_code_to_target_status function in nat/windows-nat.c used
> by both GDB and GDBserver, with the MinGW-specific logic added by
> commit 559e7e5056 ("Improve process exit status macros on MinGW")
> moved there too.
AFAIU, this basically adds a Cygwin-specific branch to the code that
determines the terminating signal and status of a program, leaving the
code for the native Windows and MinGW programs intact. I suggest to
say this in the commit log message, because as written, it sounds like
it does something for Cygwin that is not done for MinGW. Which is not
true.
> +#ifdef __CYGWIN__
> + /* /usr/include/cygwin/wait.h explains that a wait status is 16
> + bits, and looks like:
> +
> + "<1 byte info> <1 byte code>
> + <code> == 0, child has exited, info is the exit value
> + <code> == 1..7e, child has exited, code is the signal number.
> + <code> == 7f, child has stopped, info was the signal number.
> + <code> == 80, there was a core dump."
> +
> + However, when passing the wait status to native ExitProcess as a
> + native exit code, cygwin1.dll swaps the <info>/<code> bytes.
> + Swap them back into a wait status here. */
> + int wstatus = ((exit_code & 0xff) << 8) | ((exit_code >> 8) & 0xff);
Should the commentary say something about _why_ we swap the bytes
here? I know very little about Cygwin, but my naïve view is that when
a Cygwin program is run from another Cygwin program, no such swapping
should be needed, is that right? One should just use the macros from
the sys/wait.h header, right? If so, why do we need to swap the bytes
here, and how is "passing the wait status to native ExitProcess as a
native exit code" relevant to what this part of GDB needs to do?
Other than these questions, the MinGW part of the code looks okay to
me, thanks.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW
2026-05-22 0:16 ` [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW Pedro Alves
@ 2026-05-22 7:18 ` Eli Zaretskii
0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2026-05-22 7:18 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> From: Pedro Alves <pedro@palves.net>
> Date: Fri, 22 May 2026 01:16:26 +0100
>
> This commit fixes several issues in gdb.python/py-events.exp for
> Cygwin and MinGW. With these fixed, the testcase passes cleanly on
> Cygwin. I haven't tested on MinGW, but at least the test should be
> able to compile & run there now.
>
> 1) - GDB prints Windows thread IDs in hex:
>
> (gdb) thread
> [Current thread is 1 (Thread 9528.0xa9c)]
>
> The corrent code assume decimal, so we only (incorrectly) extract the
> "0" after the dot.
>
> 2) - Thread and process ID number spaces are different.
>
> The current code assumes that the extract thread is is the same number
^^
Typo: should be "ID".
> as the extracted process id, which is not true on Windows.
>
> 3) - there is no "info proc" command on Windows
>
> The testcase is using "info proc" to extract the inferior's process
> it. But "info proc" does not exist on all targets, including Windows.
^^
Same here.
Thanks.
(I don't add the reviewed-by signature, because I cannot review the
expect code.)
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1
2026-05-22 0:16 ` [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1 Pedro Alves
@ 2026-05-22 13:54 ` Tom Tromey
0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2026-05-22 13:54 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
Pedro> This commit fixes it, by passing the byte size of the destination
Pedro> buffer.
This looks good, thanks.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2
2026-05-22 0:16 ` [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2 Pedro Alves
@ 2026-05-22 14:37 ` Tom Tromey
2026-05-25 16:43 ` Pedro Alves
0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2026-05-22 14:37 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
Pedro> On the gdbserver side, we're just completely missing the
Pedro> cygwin_conv_path logic. This commit adds it. The code isn't shared
Pedro> with GDB because GDB uses wide chars, and gdbserver uses narrow char.
I wonder why, and whether this results in any differences in behavior.
Anyway this looks good.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin
2026-05-22 0:16 ` [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin Pedro Alves
@ 2026-05-22 15:09 ` Tom Tromey
0 siblings, 0 replies; 13+ messages in thread
From: Tom Tromey @ 2026-05-22 15:09 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
Pedro> gdb.base/exitsignal.exp fails on Cygwin partly because it doesn't take
Pedro> that into account. This commit fixes it.
Pedro> In addition, the typical adjustement for the fact that all programs
Pedro> are multi-threaded on Cygwin is also necessary.
Looks reasonable to me.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2
2026-05-22 14:37 ` Tom Tromey
@ 2026-05-25 16:43 ` Pedro Alves
0 siblings, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2026-05-25 16:43 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 2026-05-22 15:37, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <pedro@palves.net> writes:
>
> Pedro> On the gdbserver side, we're just completely missing the
> Pedro> cygwin_conv_path logic. This commit adds it. The code isn't shared
> Pedro> with GDB because GDB uses wide chars, and gdbserver uses narrow char.
>
> I wonder why, and whether this results in any differences in behavior.
>
For the "why", I think it's just historical.
See:
https://inbox.sourceware.org/gdb-patches/20100228150844.GH5683@calimero.vinschen.de/
... for when GDB started using the Wide versions, which talks about the Ansi limitations.
And then, nobody ever adjusted GDBserver.
> Anyway this looks good.
> Approved-By: Tom Tromey <tom@tromey.com>
Thanks, I merged patches 1, 2, and 3. I'll be sending a v2 with a new version of the remainder, in a sec.
Pedro Alves
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 4/5] Fix exit/signal code on Cygwin
2026-05-22 7:15 ` Eli Zaretskii
@ 2026-05-25 16:47 ` Pedro Alves
0 siblings, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2026-05-25 16:47 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On 2026-05-22 08:15, Eli Zaretskii wrote:
>> From: Pedro Alves <pedro@palves.net>
...
>> This commit fixes it. To avoid duplicating code, it adds a new
>> native_exit_code_to_target_status function in nat/windows-nat.c used
>> by both GDB and GDBserver, with the MinGW-specific logic added by
>> commit 559e7e5056 ("Improve process exit status macros on MinGW")
>> moved there too.
>
> AFAIU, this basically adds a Cygwin-specific branch to the code that
> determines the terminating signal and status of a program, leaving the
> code for the native Windows and MinGW programs intact.
Yes. For v2, I split the refactor to its own patch, which I think makes
that more obvious.
> I suggest to
> say this in the commit log message, because as written, it sounds like
> it does something for Cygwin that is not done for MinGW. Which is not
> true.
Done this too, thanks.
>
>> +#ifdef __CYGWIN__
>> + /* /usr/include/cygwin/wait.h explains that a wait status is 16
>> + bits, and looks like:
>> +
>> + "<1 byte info> <1 byte code>
>> + <code> == 0, child has exited, info is the exit value
>> + <code> == 1..7e, child has exited, code is the signal number.
>> + <code> == 7f, child has stopped, info was the signal number.
>> + <code> == 80, there was a core dump."
>> +
>> + However, when passing the wait status to native ExitProcess as a
>> + native exit code, cygwin1.dll swaps the <info>/<code> bytes.
>> + Swap them back into a wait status here. */
>> + int wstatus = ((exit_code & 0xff) << 8) | ((exit_code >> 8) & 0xff);
>
> Should the commentary say something about _why_ we swap the bytes
> here? I know very little about Cygwin, but my naïve view is that when
> a Cygwin program is run from another Cygwin program, no such swapping
> should be needed, is that right? One should just use the macros from
> the sys/wait.h header, right? If so, why do we need to swap the bytes
> here, and how is "passing the wait status to native ExitProcess as a
> native exit code" relevant to what this part of GDB needs to do?
Thanks for raising the question, it made me look deeper, dig into the Cygwin code
in mode detail, and realize that in the attach case, we shouldn't do the swap.
v2 has more and better comments explaining all this, as well as handling the
attach case, and testing it too. The new comments will implicitly answer your
questions. I'll be sending v2 shortly to the list.
Pedro Alves
>
> Other than these questions, the MinGW part of the code looks okay to
> me, thanks.
>
> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-25 16:48 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-22 0:16 [PATCH 0/5] Fix a few Cygwin/MinGW problems Pedro Alves
2026-05-22 0:16 ` [PATCH 1/5] Fix "set cwd ..." on Cygwin, part 1 Pedro Alves
2026-05-22 13:54 ` Tom Tromey
2026-05-22 0:16 ` [PATCH 2/5] Fix "set cwd ..." on Cygwin, part 2 Pedro Alves
2026-05-22 14:37 ` Tom Tromey
2026-05-25 16:43 ` Pedro Alves
2026-05-22 0:16 ` [PATCH 3/5] Adjust gdb.base/exitsignal.exp for Cygwin Pedro Alves
2026-05-22 15:09 ` Tom Tromey
2026-05-22 0:16 ` [PATCH 4/5] Fix exit/signal code on Cygwin Pedro Alves
2026-05-22 7:15 ` Eli Zaretskii
2026-05-25 16:47 ` Pedro Alves
2026-05-22 0:16 ` [PATCH 5/5] Adjust gdb.python/py-events.exp for Cygwin/MinGW Pedro Alves
2026-05-22 7:18 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox