[newlib-cygwin] Cygwin: console: tty::restore really restores the previous mode

Takashi Yano via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=0bfd91d578632b9348d769d2bc8611d6e9493d3a

commit 0bfd91d578632b9348d769d2bc8611d6e9493d3a
Author: Takashi Yano <[email protected]>
Date:   Fri Mar 21 12:54:28 2025 +0900

    Cygwin: console: tty::restore really restores the previous mode
    
    Previously, tty::restore sets the console mode to a predetermined
    console mode that is widely common for many non-cygwin console apps.
    So, if a non-cygwin app that is started from cygwin process changes
    the console mode and executes cygwin sub-process, the console mode
    is changed to the predetermined mode rather than being restored the
    original mode that is set by the non-cygwin app.
    With this patch, the console mode is stored when a cygwin process is
    started from non-cygwin app, then tty::restore restores the previous
    console mode that is used by the previous non-cygwin app when the
    cygwin app exits.
    
    Addresses: https://github.com/msys2/msys2-runtime/issues/268
    Fixes: 3312f2d21f13 ("Cygwin: console: Redesign mode set strategy on close().")
    Reported-by: Eu Pin Tien, Jeremy Drake <[email protected]>
    Signed-off-by: Takashi Yano <[email protected]>

Diff:
---
 winsup/cygwin/fhandler/console.cc       | 49 ++++++++++++++++-----------------
 winsup/cygwin/local_includes/fhandler.h |  4 ++-
 winsup/cygwin/release/3.6.1             |  5 ++++
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index da335b3e3..f162698a8 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -804,6 +804,9 @@ fhandler_console::rabuflen ()
   return con_ra.rabuflen;
 }
 
+static DWORD prev_input_mode_backup;
+static DWORD prev_output_mode_backup;
+
 /* The function set_{in,out}put_mode() should be static so that they
    can be called even after the fhandler_console instance is deleted. */
 void
@@ -818,11 +821,11 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
   GetConsoleMode (p->input_handle, &oflags);
   DWORD flags = oflags
     & (ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE);
-  con.curr_input_mode = m;
   switch (m)
     {
     case tty::restore:
-      flags |= ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
+      flags = con.prev_input_mode;
+      con.prev_input_mode = prev_input_mode_backup;
       break;
     case tty::cygwin:
       flags |= ENABLE_WINDOW_INPUT;
@@ -846,6 +849,12 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
 	flags |= ENABLE_PROCESSED_INPUT;
       break;
     }
+  if (con.curr_input_mode != tty::cygwin && m == tty::cygwin)
+    {
+      prev_input_mode_backup = con.prev_input_mode;
+      con.prev_input_mode = oflags;
+    }
+  con.curr_input_mode = m;
   SetConsoleMode (p->input_handle, flags);
   if (!(oflags & ENABLE_VIRTUAL_TERMINAL_INPUT)
       && (flags & ENABLE_VIRTUAL_TERMINAL_INPUT)
@@ -868,10 +877,11 @@ fhandler_console::set_output_mode (tty::cons_mode m, const termios *t,
   if (con.orig_virtual_terminal_processing_mode)
     flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
   WaitForSingleObject (p->output_mutex, mutex_timeout);
-  con.curr_output_mode = m;
   switch (m)
     {
     case tty::restore:
+      flags = con.prev_output_mode;
+      con.prev_output_mode = prev_output_mode_backup;
       break;
     case tty::cygwin:
       if (wincap.has_con_24bit_colors () && !con_is_legacy)
@@ -883,6 +893,12 @@ fhandler_console::set_output_mode (tty::cons_mode m, const termios *t,
 	flags |= DISABLE_NEWLINE_AUTO_RETURN;
       break;
     }
+  if (con.curr_output_mode != tty::cygwin && m == tty::cygwin)
+    {
+      prev_output_mode_backup = con.prev_output_mode;
+      GetConsoleMode (p->output_handle, &con.prev_output_mode);
+    }
+  con.curr_output_mode = m;
   acquire_attach_mutex (mutex_timeout);
   DWORD resume_pid = attach_console (con.owner);
   SetConsoleMode (p->output_handle, flags);
@@ -916,7 +932,7 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
   /* Cleaning-up console mode for non-cygwin app. */
   /* conmode can be tty::restore when non-cygwin app is
      exec'ed from login shell. */
-  tty::cons_mode conmode = cons_mode_on_close (p);
+  tty::cons_mode conmode = cons_mode_on_close ();
   set_output_mode (conmode, ti, p);
   set_input_mode (conmode, ti, p);
   set_disable_master_thread (con.owner == GetCurrentProcessId ());
@@ -1978,9 +1994,8 @@ fhandler_console::close (int flag)
   if (shared_console_info[unit] && myself->ppid == 1
       && (dev_t) myself->ctty == get_device ())
     {
-      tty::cons_mode conmode = cons_mode_on_close (&handle_set);
-      set_output_mode (conmode, &get_ttyp ()->ti, &handle_set);
-      set_input_mode (conmode, &get_ttyp ()->ti, &handle_set);
+      set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
+      set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
       set_disable_master_thread (true, this);
     }
 
@@ -4687,26 +4702,10 @@ fhandler_console::fstat (struct stat *st)
 }
 
 tty::cons_mode
-fhandler_console::cons_mode_on_close (handle_set_t *p)
+fhandler_console::cons_mode_on_close ()
 {
-  const _minor_t unit = p->unit;
-
   if (myself->ppid != 1) /* Execed from normal cygwin process. */
     return tty::cygwin;
 
-  if (!process_alive (con.owner)) /* The Master process already died. */
-    return tty::restore;
-  if (con.owner == GetCurrentProcessId ()) /* Master process */
-    return tty::restore;
-
-  PROCESS_BASIC_INFORMATION pbi;
-  NTSTATUS status =
-    NtQueryInformationProcess (GetCurrentProcess (), ProcessBasicInformation,
-			       &pbi, sizeof (pbi), NULL);
-  if (NT_SUCCESS (status)
-      && con.owner == (DWORD) pbi.InheritedFromUniqueProcessId)
-    /* The parent is the stub process. */
-    return tty::restore;
-
-  return tty::native; /* Otherwise */
+  return tty::restore; /* otherwise, restore */
 }
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index b00a1a195..8c71d8495 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2146,6 +2146,8 @@ class dev_console
   bool disable_master_thread;
   tty::cons_mode curr_input_mode;
   tty::cons_mode curr_output_mode;
+  DWORD prev_input_mode;
+  DWORD prev_output_mode;
   bool master_thread_suspended;
   int num_processed; /* Number of input events in the current input buffer
 			already processed by cons_master_thread(). */
@@ -2366,7 +2368,7 @@ private:
 
   void setup_pcon_hand_over ();
   static void pcon_hand_over_proc ();
-  static tty::cons_mode cons_mode_on_close (handle_set_t *);
+  static tty::cons_mode cons_mode_on_close ();
 
   friend tty_min * tty_list::get_cttyp ();
 };
diff --git a/winsup/cygwin/release/3.6.1 b/winsup/cygwin/release/3.6.1
new file mode 100644
index 000000000..0b54b5fd3
--- /dev/null
+++ b/winsup/cygwin/release/3.6.1
@@ -0,0 +1,5 @@
+Fixes:
+------
+
+- Console mode is really restored to the previous mode.
+  Addresses: https://github.com/msys2/msys2-runtime/issues/268
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.