From c1dc47f53cccf633f3079db25a5b41adaee940a8 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 5 Dec 2022 11:15:09 -0700 Subject: [PATCH] Refactor code to check for terminal sharing This refactors the code to check for terminal sharing. is_gdb_terminal is exported, and sharing_input_terminal_1 is renamed, slightly refactored, and moved to posix-hdep.c. A new Windows-specific implementation of this function is added to mingw-hdep.c. MSDN has a warning about GetConsoleProcessList This API is not recommended and does not have a virtual terminal equivalent. [...] Applications remoting via cross-platform utilities and transports like SSH may not work as expected if using this API. However, we believe this isn't likely to be an issue for gdb. --- gdb/inferior.h | 11 +++++++++++ gdb/inflow.c | 27 +++------------------------ gdb/mingw-hdep.c | 31 ++++++++++++++++++++++++++++++- gdb/posix-hdep.c | 20 +++++++++++++++++++- 4 files changed, 63 insertions(+), 26 deletions(-) diff --git a/gdb/inferior.h b/gdb/inferior.h index 69525a2e053..547e8751d08 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -167,6 +167,17 @@ extern void default_print_float_info (struct gdbarch *gdbarch, frame_info_ptr frame, const char *args); +/* Try to determine whether TTY is GDB's input terminal. Returns + TRIBOOL_UNKNOWN if we can't tell. */ + +extern tribool is_gdb_terminal (const char *tty); + +/* Helper for sharing_input_terminal. Try to determine whether pid + PID is using the same TTY for input as GDB is. Returns + TRIBOOL_UNKNOWN if we can't tell. */ + +extern tribool sharing_input_terminal (int pid); + extern void child_terminal_info (struct target_ops *self, const char *, int); extern void child_terminal_ours (struct target_ops *self); diff --git a/gdb/inflow.c b/gdb/inflow.c index da2005a9318..cd4de98d3ed 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -212,10 +212,9 @@ gdb_save_tty_state (void) } } -/* Try to determine whether TTY is GDB's input terminal. Returns - TRIBOOL_UNKNOWN if we can't tell. */ +/* See inferior.h. */ -static tribool +tribool is_gdb_terminal (const char *tty) { struct stat gdb_tty; @@ -236,26 +235,6 @@ is_gdb_terminal (const char *tty) : TRIBOOL_FALSE); } -/* Helper for sharing_input_terminal. Try to determine whether - inferior INF is using the same TTY for input as GDB is. Returns - TRIBOOL_UNKNOWN if we can't tell. */ - -static tribool -sharing_input_terminal_1 (inferior *inf) -{ - /* Using host-dependent code here is fine, because the - child_terminal_foo functions are meant to be used by child/native - targets. */ -#if defined (__linux__) || defined (__sun__) - char buf[100]; - - xsnprintf (buf, sizeof (buf), "/proc/%d/fd/0", inf->pid); - return is_gdb_terminal (buf); -#else - return TRIBOOL_UNKNOWN; -#endif -} - /* Return true if the inferior is using the same TTY for input as GDB is. If this is true, then we save/restore terminal flags/state. @@ -287,7 +266,7 @@ sharing_input_terminal (inferior *inf) { terminal_info *tinfo = get_inflow_inferior_data (inf); - tribool res = sharing_input_terminal_1 (inf); + tribool res = sharing_input_terminal (inf->pid); if (res == TRIBOOL_UNKNOWN) { diff --git a/gdb/mingw-hdep.c b/gdb/mingw-hdep.c index 651e795216d..9d0337cf4ef 100644 --- a/gdb/mingw-hdep.c +++ b/gdb/mingw-hdep.c @@ -21,8 +21,8 @@ #include "main.h" #include "serial.h" #include "gdbsupport/event-loop.h" - #include "gdbsupport/gdb_select.h" +#include "inferior.h" #include @@ -371,3 +371,32 @@ gdb_console_fputs (const char *linebuf, FILE *fstream) last_style = style; return 1; } + +/* See inferior.h. */ + +tribool +sharing_input_terminal (int pid) +{ + std::vector results (10); + DWORD len = 0; + while (true) + { + len = GetConsoleProcessList (results.data (), results.size ()); + /* Note that LEN == 0 is a failure, but we can treat it the same + as a "no". */ + if (len < results.size ()) + break; + + results.resize (len); + } + /* In case the vector was too big. */ + results.resize (len); + if (std::find (results.begin (), results.end (), pid) != results.end ()) + { + /* The pid is in the list sharing the console, so don't + interrupt the inferior -- it will get the signal itself. */ + return TRIBOOL_TRUE; + } + + return TRIBOOL_FALSE; +} diff --git a/gdb/posix-hdep.c b/gdb/posix-hdep.c index 3d44338d2ae..26211978d06 100644 --- a/gdb/posix-hdep.c +++ b/gdb/posix-hdep.c @@ -19,8 +19,8 @@ #include "defs.h" #include "gdbsupport/event-loop.h" - #include "gdbsupport/gdb_select.h" +#include "inferior.h" /* Wrapper for select. Nothing special needed on POSIX platforms. */ @@ -38,3 +38,21 @@ gdb_console_fputs (const char *buf, FILE *f) { return 0; } + +/* See inferior.h. */ + +tribool +sharing_input_terminal (int pid) +{ + /* Using host-dependent code here is fine, because the + child_terminal_foo functions are meant to be used by child/native + targets. */ +#if defined (__linux__) || defined (__sun__) + char buf[100]; + + xsnprintf (buf, sizeof (buf), "/proc/%d/fd/0", pid); + return is_gdb_terminal (buf); +#else + return TRIBOOL_UNKNOWN; +#endif +} -- 2.30.2