From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1551) id 802023858C78; Tue, 27 Feb 2024 14:30:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 802023858C78 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1709044234; bh=6E4vZrKwGWzijV9tHPEqeHHNQhVWx21TfU/tpS7JH6U=; h=From:To:Subject:Date:From; b=JXTSBvspGakejkGQj4tBl92YUGCoo7mNycfR8B1cGLa6Nddo7tuxKbhpkq5Wq06N1 GM31Kus6QZbCxD8QMJIXTj/WFfUryuDRofCWXctVYH2wre8B7Ku8C3hKX4ylSEtX66 1BGN/a5BDiJyKr2M5M4dxu9ppwko6eUrlvlbhiRU= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Pedro Alves To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Cygwin: Fix putting inferior in foreground (fix input) X-Act-Checkin: binutils-gdb X-Git-Author: Pedro Alves X-Git-Refname: refs/heads/master X-Git-Oldrev: f1c4160786e08cf0ec4c89c5c0466deab0855ab8 X-Git-Newrev: dfec66ffff42d8274132f6df20d5281e10f0e746 Message-Id: <20240227143034.802023858C78@sourceware.org> Date: Tue, 27 Feb 2024 14:30:34 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Ddfec66ffff42= d8274132f6df20d5281e10f0e746 commit dfec66ffff42d8274132f6df20d5281e10f0e746 Author: Pedro Alves Date: Thu May 6 20:59:14 2021 +0100 Cygwin: Fix putting inferior in foreground (fix input) =20 gdb.base/interrupt.exp reveals that inferior input is broken on Cygwin: =20 (gdb) continue Continuing. talk to me baby Input/output error <<< BAD PASS: gdb.base/interrupt.exp: process is alive a [Thread 10688.0x2590 exited with code 1] [Thread 10688.0x248c exited with code 1] [Thread 10688.0x930 exited with code 1] [Thread 10688.0x2c98 exited with code 1] =20 Program terminated with signal SIGHUP, Hangup. The program no longer exists. (gdb) FAIL: gdb.base/interrupt.exp: child process ate our char a Ambiguous command "a": actions, add-auto-load-safe-path, add-auto-loa= d-scripts-directory, add-inferior... (gdb) ERROR: "" is not a unique command name. =20 The problem is that inflow.c:child_terminal_inferior is failing to put the inferior in the foreground, because we're passing down the inferior's Windows PID instead of the Cygwin PID to Cygwin tcsetpgrp. =20 That is fixed by this commit. Afterwards we will get: =20 (gdb) continue Continuing. talk to me baby PASS: gdb.base/interrupt.exp: process is alive a a <<< GO= OD PASS: gdb.base/interrupt.exp: child process ate our char [New Thread 7236.0x1c58] =20 Thread 6 received signal SIGINT, Interrupt. <<< ne= w thread spawned for SIGINT [Switching to Thread 7236.0x1c58] 0x00007ffa6643ea6b in TlsGetValue () from /cygdrive/c/Windows/System3= 2/KERNELBASE.dll (gdb) FAIL: gdb.base/interrupt.exp: send_gdb control C =20 We still have the FAIL seen above because this change has another consequence. By failing to put the inferior in the foreground correctly, Ctrl-C was always reaching GDB first. Now that the inferior is put in the foreground properly, Ctrl-C reaches the inferior first, which results in a Windows Ctrl-C event, which results in Windows injecting a new thread in the inferior to report the Ctrl-C exception =3D> SIGINT. That is, running the test manually: =20 Before patch: =20 (gdb) c Continuing. [New Thread 2352.0x1f5c] [New Thread 2352.0x1988] [New Thread 2352.0x18cc] <<< Ctrl-C p= ressed. Thread 7 received signal SIGTRAP, Trace/breakpoint trap. [Switching to Thread 2352.0x18cc] 0x00007ffa68930b11 in ntdll!DbgBreakPoint () from /cygdrive/c/Windows= /SYSTEM32/ntdll.dll (gdb) =20 Above, GDB got the SIGINT, and it manually passes it down the inferior, which reaches windows_nat_target::interrupt(), which interrupts the inferior with DebugBreakProcess (which injects a new thread in the inferior that executes an int3 instruction). =20 After this patch, we have (with "set debugexceptions on" so DBG_CONTROL_C is visible): =20 (gdb) c Continuing. [New Thread 9940.0x1168] [New Thread 9940.0x5f8] gdb: Target exception MS_VC_EXCEPTION at 0x7ffa6638cf19 gdb: Target exception MS_VC_EXCEPTION at 0x7ffa6638cf19 [New Thread 9940.0x3d8] gdb: Target exception DBG_CONTROL_C at 0x7ffa6643ea6b <<< Ctrl-C =20 Thread 7 received signal SIGINT, Interrupt. <<< new injec= ted thread [Switching to Thread 9940.0x3d8] 0x00007ffa6643ea6b in TlsGetValue () from /cygdrive/c/Windows/System3= 2/KERNELBASE.dll (gdb) =20 This new behavior is exactly the same as what you see with a MinGW GDB build. Also, SIGINT reaching inferior first is what you get on Linux as well currently. =20 I wrote an initial fix for this before I discovered that Cygwin downstream had a similar change, so I then combined the patches. I am adding a Co-Authored-By for that reason. =20 Co-Authored-By: Takashi Yano Approved-By: Tom Tromey Change-Id: I3a8c3355784c6a817dbd345ba9dac24be06c4b3f Diff: --- gdb/inflow.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/gdb/inflow.c b/gdb/inflow.c index a413957a1dd..3dd70b97fe5 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -40,6 +40,10 @@ #include #endif =20 +#ifdef __CYGWIN__ +#include +#endif + #ifndef O_NOCTTY #define O_NOCTTY 0 #endif @@ -345,11 +349,25 @@ child_terminal_inferior (struct target_ops *self) then restore whatever was the foreground pgrp the last time the inferior was running. See also comments describing terminal_state::process_group. */ -#ifdef HAVE_GETPGID - result =3D tcsetpgrp (0, getpgid (inf->pid)); -#else - result =3D tcsetpgrp (0, tinfo->process_group); + pid_t pgrp =3D tinfo->process_group; +#ifdef __CYGWIN__ + /* The Windows native target uses Win32 routines to run or + attach to processes (CreateProcess / DebugActiveProcess), + so a Cygwin inferior has a Windows PID, rather than a + Cygwin PID. We want to pass the Cygwin PID to Cygwin + tcsetpgrp if we have a Cygwin inferior, so try to convert + first. If we have a non-Cygwin inferior, we'll end up + passing down the WINPID to tcsetpgrp, stored in + terminal_state::process_group. tcsetpgrp still succeeds + in that case, and it seems preferable to switch the + foreground pgrp away from GDB, for consistency. */ + pid_t cygpid =3D cygwin_internal (CW_WINPID_TO_CYGWIN_PID, inf->pid); + if (cygpid <=3D cygwin_internal (CW_MAX_CYGWIN_PID)) + pgrp =3D getpgid (cygpid); +#elif defined (HAVE_GETPGID) + pgrp =3D getpgid (inf->pid); #endif + result =3D tcsetpgrp (0, pgrp); if (result =3D=3D -1) { #if 0