From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id 912A13857434; Sat, 14 May 2022 22:37:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 912A13857434 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Takashi Yano To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/cygwin-3_3-branch] Cygwin: pty: Fix script command crash on console in Win7. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/cygwin-3_3-branch X-Git-Oldrev: 65879410256b5f477ff56b0fdab7007fdfe0ec7f X-Git-Newrev: 8dde370720b63bc93b88852fadd2f128009c47dc Message-Id: <20220514223714.912A13857434@sourceware.org> Date: Sat, 14 May 2022 22:37:14 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 14 May 2022 22:37:14 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D8dde370720b= 63bc93b88852fadd2f128009c47dc commit 8dde370720b63bc93b88852fadd2f128009c47dc Author: Takashi Yano Date: Sat May 14 20:35:43 2022 +0900 Cygwin: pty: Fix script command crash on console in Win7. =20 - Previously, the command "cmd /c script -c cmd" in console of Win7 crashes. This seems to be due to a bug (?) of AttachConsole(). This patch adds workaround for this issue. =20 Currently, pty reattaches to the console of the process which is predetermined by ConsoleProcessList() after temporarily attaching to another console. After that, the console output handle opened with the name "CONOUT$" may not be accessible in Win7 or Vista. This seems to happen when the attached process does not have the same handle even if the console attached is the same. With this patch, cygwin-console-helper which is started when pty master is opened in console, is utilized to be a target process to which pty reattaches if the OS is Win7 or Vista. Diff: --- winsup/cygwin/fhandler.h | 6 +++ winsup/cygwin/fhandler_termios.cc | 4 +- winsup/cygwin/fhandler_tty.cc | 70 +++++++++++++++++++++++++= +++- winsup/cygwin/wincap.cc | 11 +++++ winsup/cygwin/wincap.h | 2 + winsup/utils/mingw/cygwin-console-helper.cc | 2 +- 6 files changed, 91 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 291aa5bf1..2ff99aeae 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1983,6 +1983,7 @@ class fhandler_termios: public fhandler_base virtual void cleanup_before_exit () {} virtual bool need_console_handler () { return false; } virtual bool need_send_ctrl_c_event () { return true; } + virtual DWORD get_helper_pid () { return 0; } }; =20 enum ansi_intensity @@ -2466,6 +2467,7 @@ public: HANDLE from_slave_nat; HANDLE output_mutex; tty *ttyp; + DWORD helper_pid; }; private: int pktmode; // non-zero if pty in a packet mode. @@ -2477,6 +2479,9 @@ private: HANDLE to_master, from_master; cygthread *master_fwd_thread; // Master forwarding thread HANDLE thread_param_copied_event; + HANDLE helper_goodbye; + HANDLE helper_h_process; + DWORD helper_pid; =20 public: HANDLE get_echo_handle () const { return echo_r; } @@ -2531,6 +2536,7 @@ public: void get_master_fwd_thread_param (master_fwd_thread_param_t *p); void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho =3D m; } bool need_send_ctrl_c_event (); + DWORD get_helper_pid () { return helper_pid; } }; =20 class fhandler_dev_null: public fhandler_base diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_ter= mios.cc index 8dd38053c..f4d7493c8 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -359,7 +359,9 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhan= dler_termios *fh) acquire_attach_mutex (mutex_timeout); pinfo pinfo_resume =3D pinfo (myself->ppid); DWORD resume_pid =3D 0; - if (pinfo_resume) + if (fh && fh->get_helper_pid ()) + resume_pid =3D fh->get_helper_pid (); + else if (pinfo_resume) resume_pid =3D pinfo_resume->dwProcessId; else resume_pid =3D fhandler_pty_common::get_console_process_id diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 0cd69f3ca..399b6efaa 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -534,7 +534,9 @@ fhandler_pty_master::accept_input () acquire_attach_mutex (mutex_timeout); pinfo pinfo_resume =3D pinfo (myself->ppid); DWORD resume_pid; - if (pinfo_resume) + if (helper_pid) + resume_pid =3D helper_pid; + else if (pinfo_resume) resume_pid =3D pinfo_resume->dwProcessId; else resume_pid =3D get_console_process_id (myself->dwProcessId, false); @@ -2170,6 +2172,16 @@ fhandler_pty_master::close () get_ttyp ()->stop_fwd_thread =3D true; WriteFile (to_master_nat, "", 0, &len, NULL); master_fwd_thread->detach (); + if (helper_goodbye) + { + SetEvent (helper_goodbye); + WaitForSingleObject (helper_h_process, INFINITE); + CloseHandle (helper_h_process); + CloseHandle (helper_goodbye); + helper_pid =3D 0; + helper_h_process =3D 0; + helper_goodbye =3D NULL; + } } } =20 @@ -2878,7 +2890,9 @@ fhandler_pty_master::pty_master_fwd_thread (const mas= ter_fwd_thread_param_t *p) acquire_attach_mutex (mutex_timeout); pinfo pinfo_resume =3D pinfo (myself->ppid); DWORD resume_pid; - if (pinfo_resume) + if (p->helper_pid) + resume_pid =3D p->helper_pid; + else if (pinfo_resume) resume_pid =3D pinfo_resume->dwProcessId; else resume_pid =3D get_console_process_id (myself->dwProcessId, false); @@ -3071,6 +3085,57 @@ fhandler_pty_master::setup () goto err; } WaitForSingleObject (thread_param_copied_event, INFINITE); + + if (wincap.has_broken_attach_console () + && _major (myself->ctty) =3D=3D DEV_CONS_MAJOR + && !(!pinfo (myself->ppid) && getenv ("ConEmuPID"))) + { + HANDLE hello =3D CreateEvent (&sec_none, true, false, NULL); + HANDLE goodbye =3D CreateEvent (&sec_none, true, false, NULL); + WCHAR cmd[MAX_PATH]; + path_conv helper ("/bin/cygwin-console-helper.exe"); + size_t len =3D helper.get_wide_win32_path_len (); + helper.get_wide_win32_path (cmd); + __small_swprintf (cmd + len, L" %p %p", hello, goodbye); + + STARTUPINFOEXW si; + PROCESS_INFORMATION pi; + ZeroMemory (&si, sizeof (si)); + si.StartupInfo.cb =3D sizeof (STARTUPINFOEXW); + + SIZE_T bytesRequired; + InitializeProcThreadAttributeList (NULL, 1, 0, &bytesRequired); + si.lpAttributeList =3D (PPROC_THREAD_ATTRIBUTE_LIST) + HeapAlloc (GetProcessHeap (), 0, bytesRequired); + InitializeProcThreadAttributeList (si.lpAttributeList, + 1, 0, &bytesRequired); + HANDLE handles_to_inherit[] =3D {hello, goodbye}; + UpdateProcThreadAttribute (si.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + handles_to_inherit, + sizeof (handles_to_inherit), + NULL, NULL); + if (CreateProcessW (NULL, cmd, &sec_none, &sec_none, + TRUE, EXTENDED_STARTUPINFO_PRESENT, + NULL, NULL, &si.StartupInfo, &pi)) + { + WaitForSingleObject (hello, INFINITE); + CloseHandle (hello); + CloseHandle (pi.hThread); + helper_goodbye =3D goodbye; + helper_pid =3D pi.dwProcessId; + helper_h_process =3D pi.hProcess; + } + else + { + CloseHandle (hello); + CloseHandle (goodbye); + } + DeleteProcThreadAttributeList (si.lpAttributeList); + HeapFree (GetProcessHeap (), 0, si.lpAttributeList); + } + master_fwd_thread =3D new cygthread (::pty_master_fwd_thread, this, "pty= mf"); if (!master_fwd_thread) { @@ -3875,6 +3940,7 @@ fhandler_pty_master::get_master_fwd_thread_param (mas= ter_fwd_thread_param_t *p) p->from_slave_nat =3D from_slave_nat; p->output_mutex =3D output_mutex; p->ttyp =3D get_ttyp (); + p->helper_pid =3D helper_pid; SetEvent (thread_param_copied_event); } =20 diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 6c79d8710..af34de5a4 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -51,6 +51,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll= _common"), shared)) =3D { has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:false, has_query_process_handle_info:false, + has_broken_attach_console:true, }, }; =20 @@ -87,6 +88,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_com= mon"), shared)) =3D { has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:false, has_query_process_handle_info:false, + has_broken_attach_console:true, }, }; =20 @@ -123,6 +125,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_c= ommon"), shared)) =3D { has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:false, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -159,6 +162,7 @@ wincaps wincap_8_1 __attribute__((section (".cygwin_dll= _common"), shared)) =3D { has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:false, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -195,6 +199,7 @@ wincaps wincap_10_1507 __attribute__((section (".cygwi= n_dll_common"), shared)) has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:false, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -231,6 +236,7 @@ wincaps wincap_10_1607 __attribute__((section (".cygwi= n_dll_common"), shared)) has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -267,6 +273,7 @@ wincaps wincap_10_1703 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_linux_tcp_keepalive_sockopts:false, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -303,6 +310,7 @@ wincaps wincap_10_1709 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_linux_tcp_keepalive_sockopts:true, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -339,6 +347,7 @@ wincaps wincap_10_1803 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_linux_tcp_keepalive_sockopts:true, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -375,6 +384,7 @@ wincaps wincap_10_1809 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_linux_tcp_keepalive_sockopts:true, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 @@ -411,6 +421,7 @@ wincaps wincap_10_1903 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_linux_tcp_keepalive_sockopts:true, has_tcp_maxrtms:true, has_query_process_handle_info:true, + has_broken_attach_console:false, }, }; =20 diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 7249b9518..63911d079 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -45,6 +45,7 @@ struct wincaps unsigned has_linux_tcp_keepalive_sockopts : 1; unsigned has_tcp_maxrtms : 1; unsigned has_query_process_handle_info : 1; + unsigned has_broken_attach_console : 1; }; }; =20 @@ -113,6 +114,7 @@ public: bool IMPLEMENT (has_linux_tcp_keepalive_sockopts) bool IMPLEMENT (has_tcp_maxrtms) bool IMPLEMENT (has_query_process_handle_info) + bool IMPLEMENT (has_broken_attach_console) =20 void disable_case_sensitive_dirs () { diff --git a/winsup/utils/mingw/cygwin-console-helper.cc b/winsup/utils/min= gw/cygwin-console-helper.cc index 66004bd15..80d15e3f3 100644 --- a/winsup/utils/mingw/cygwin-console-helper.cc +++ b/winsup/utils/mingw/cygwin-console-helper.cc @@ -6,11 +6,11 @@ main (int argc, char **argv) char *end; if (argc < 3) exit (1); + SetConsoleCtrlHandler (NULL, TRUE); HANDLE h =3D (HANDLE) strtoull (argv[1], &end, 0); SetEvent (h); if (argc =3D=3D 4) /* Pseudo console helper mode for PTY */ { - SetConsoleCtrlHandler (NULL, TRUE); HANDLE hPipe =3D (HANDLE) strtoull (argv[3], &end, 0); char buf[64]; sprintf (buf, "StdHandles=3D%p,%p\n",