From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id D0E363858431; Tue, 1 Mar 2022 10:43:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D0E363858431 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: pty: Reorganize the code path of setting up and closing pcon. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/master X-Git-Oldrev: fbfea31dd9b9ecc4ffb160d91bb046688c3544b9 X-Git-Newrev: 1e6c51d74136d47b1d961a9d8d8ccb6478cfd3a8 Message-Id: <20220301104337.D0E363858431@sourceware.org> Date: Tue, 1 Mar 2022 10:43:37 +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: Tue, 01 Mar 2022 10:43:37 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D1e6c51d7413= 6d47b1d961a9d8d8ccb6478cfd3a8 commit 1e6c51d74136d47b1d961a9d8d8ccb6478cfd3a8 Author: Takashi Yano Date: Tue Mar 1 18:04:35 2022 +0900 Cygwin: pty: Reorganize the code path of setting up and closing pcon. =20 - This patch reorganizes the code path of setting-up and cleaning-up of the pseudo console to improve readability and maintainability of pty code. Diff: --- winsup/cygwin/fhandler.h | 10 +- winsup/cygwin/fhandler_termios.cc | 2 +- winsup/cygwin/fhandler_tty.cc | 283 ++++++++++++++++++++--------------= ---- 3 files changed, 153 insertions(+), 142 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 7646f09cc..919479948 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -2389,8 +2389,10 @@ class fhandler_pty_slave: public fhandler_pty_common fh->copy_from (this); return fh; } - bool setup_pseudoconsole (bool nopcon); + bool setup_pseudoconsole (); + static DWORD get_winpid_to_hand_over (tty *ttyp, DWORD force_switch_to); static void close_pseudoconsole (tty *ttyp, DWORD force_switch_to =3D 0); + static void hand_over_only (tty *ttyp, DWORD force_switch_to =3D 0); bool term_has_pcon_cap (const WCHAR *env); void set_switch_to_pcon (void); void reset_switch_to_pcon (void); @@ -2407,10 +2409,10 @@ class fhandler_pty_slave: public fhandler_pty_common void setup_for_non_cygwin_app (bool nopcon, PWCHAR envblock, bool stdin_is_ptys); static void cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp, - bool stdin_is_ptys); + bool stdin_is_ptys, + DWORD force_switch_to =3D 0); void setpgid_aux (pid_t pid); - static void close_pseudoconsole_if_necessary (tty *ttyp, - fhandler_termios *fh); + static void release_ownership_of_nat_pipe (tty *ttyp, fhandler_termios *= fh); }; =20 #define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit)) diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_ter= mios.cc index 094842038..a29129486 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -397,7 +397,7 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhan= dler_termios *fh) pseudo console because this process attached to it before sending CTRL_C_EVENT. In this case, closing pseudo console is necessary. */ - fhandler_pty_slave::close_pseudoconsole_if_necessary (ttyp, fh); + fhandler_pty_slave::release_ownership_of_nat_pipe (ttyp, fh); FreeConsole (); if (resume_pid && console_exists) AttachConsole (resume_pid); diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 7b099dcb9..3d74f9a0c 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -236,20 +236,18 @@ atexit_func (void) fhandler_base *fh =3D cfd; fhandler_pty_slave *ptys =3D (fhandler_pty_slave *) fh; tty *ttyp =3D (tty *) ptys->tc (); - HANDLE from =3D ptys->get_handle_nat (); - HANDLE input_available_event =3D ptys->get_input_available_event (); - if (ttyp->getpgid () =3D=3D myself->pgid - && GetStdHandle (STD_INPUT_HANDLE) =3D=3D ptys->get_handle () - && ttyp->pcon_input_state_eq (tty::to_nat) && !force_switch_to) + bool stdin_is_ptys =3D + GetStdHandle (STD_INPUT_HANDLE) =3D=3D ptys->get_handle (); + struct fhandler_pty_slave::handle_set_t handles =3D { - WaitForSingleObject (ptys->input_mutex, mutex_timeout); - fhandler_pty_slave::transfer_input (tty::to_cyg, from, ttyp, - input_available_event); - ReleaseMutex (ptys->input_mutex); - } - WaitForSingleObject (ptys->pcon_mutex, INFINITE); - ptys->close_pseudoconsole (ttyp, force_switch_to); - ReleaseMutex (ptys->pcon_mutex); + ptys->get_handle_nat (), + ptys->get_input_available_event (), + ptys->input_mutex, + ptys->pcon_mutex + }; + fhandler_pty_slave::cleanup_for_non_cygwin_app (&handles, ttyp, + stdin_is_ptys, + force_switch_to); break; } CloseHandle (h_gdb_process); @@ -1089,19 +1087,8 @@ fhandler_pty_slave::set_switch_to_pcon (void) setup_locale (); myself->exec_dwProcessId =3D myself->dwProcessId; myself->process_state |=3D PID_NEW_PG; /* Marker for pcon_fg */ - bool nopcon =3D (disable_pcon || !term_has_pcon_cap (NULL)); - WaitForSingleObject (pcon_mutex, INFINITE); - bool pcon_enabled =3D setup_pseudoconsole (nopcon); - ReleaseMutex (pcon_mutex); - if (!pcon_enabled && get_ttyp ()->getpgid () =3D=3D myself->pgid - && GetStdHandle (STD_INPUT_HANDLE) =3D=3D get_handle () - && get_ttyp ()->pcon_input_state_eq (tty::to_cyg)) - { - WaitForSingleObject (input_mutex, mutex_timeout); - transfer_input (tty::to_nat, get_handle (), get_ttyp (), - input_available_event); - ReleaseMutex (input_mutex); - } + bool stdin_is_ptys =3D GetStdHandle (STD_INPUT_HANDLE) =3D=3D get_ha= ndle (); + setup_for_non_cygwin_app (false, NULL, stdin_is_ptys); } } =20 @@ -1161,7 +1148,10 @@ fhandler_pty_slave::reset_switch_to_pcon (void) return; bool need_restore_handles =3D get_ttyp ()->pcon_activated; WaitForSingleObject (pcon_mutex, INFINITE); - close_pseudoconsole (get_ttyp ()); + if (get_ttyp ()->pcon_activated) + close_pseudoconsole (get_ttyp ()); + else + hand_over_only (get_ttyp ()); ReleaseMutex (pcon_mutex); if (need_restore_handles) { @@ -3218,22 +3208,8 @@ fhandler_pty_common::process_opost_output (HANDLE h,= const void *ptr, Slave process will attach to the pseudo console in the helper process using AttachConsole(). */ bool -fhandler_pty_slave::setup_pseudoconsole (bool nopcon) +fhandler_pty_slave::setup_pseudoconsole () { - /* Setting switch_to_pcon_in is necessary even if - pseudo console will not be activated. */ - fhandler_base *fh =3D ::cygheap->fdtab[0]; - if (fh && fh->get_major () =3D=3D DEV_PTYS_MAJOR) - { - fhandler_pty_slave *ptys =3D (fhandler_pty_slave *) fh; - ptys->get_ttyp ()->switch_to_pcon_in =3D true; - if (!pcon_pid_alive (ptys->get_ttyp ()->pcon_pid)) - ptys->get_ttyp ()->pcon_pid =3D myself->exec_dwProcessId; - } - - if (nopcon) - return false; - /* If the legacy console mode is enabled, pseudo console seems not to work as expected. To determine console mode, registry key ForceV2 in HKEY_CURRENT_USER\Console is checked. */ @@ -3249,7 +3225,7 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon) =20 HANDLE hpConIn, hpConOut; if (get_ttyp ()->pcon_activated) - { + { /* The pseudo console is already activated. */ if (GetStdHandle (STD_INPUT_HANDLE) =3D=3D get_handle ()) { /* Send CSI6n just for requesting transfer input. */ DWORD n; @@ -3287,7 +3263,7 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon) HPCON hpcon; =20 do - { + { /* Create new pseudo console */ COORD size =3D { (SHORT) get_ttyp ()->winsize.ws_col, (SHORT) get_ttyp ()->winsize.ws_row @@ -3519,10 +3495,10 @@ fallback: return false; } =20 -/* The function close_pseudoconsole() should be static so that it can - be called even after the fhandler_pty_slave instance is deleted. */ -void -fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to) +/* Find a process to which the ownership of nat pipe should be handed over= */ +DWORD +fhandler_pty_slave::get_winpid_to_hand_over (tty *ttyp, + DWORD force_switch_to) { DWORD switch_to =3D 0; if (force_switch_to) @@ -3532,106 +3508,120 @@ fhandler_pty_slave::close_pseudoconsole (tty *tty= p, DWORD force_switch_to) } else if (pcon_pid_self (ttyp->pcon_pid)) { - /* Search another process which attaches to the pseudo console */ + /* Search another native process which attaches to the same console = */ DWORD current_pid =3D myself->exec_dwProcessId ?: myself->dwProcessI= d; switch_to =3D get_console_process_id (current_pid, false, true, true= ); if (!switch_to) switch_to =3D get_console_process_id (current_pid, false, true, false); } - if (ttyp->pcon_activated) + return switch_to; +} + +void +fhandler_pty_slave::hand_over_only (tty *ttyp, DWORD force_switch_to) +{ + if (pcon_pid_self (ttyp->pcon_pid)) { - ttyp->previous_code_page =3D GetConsoleCP (); - ttyp->previous_output_code_page =3D GetConsoleOutputCP (); - if (pcon_pid_self (ttyp->pcon_pid)) + DWORD switch_to =3D get_winpid_to_hand_over (ttyp, force_switch_to); + if (switch_to) + /* The process switch_to takes over the ownership of the nat pipe. */ + ttyp->pcon_pid =3D switch_to; + else { - if (switch_to) - { - /* Change pseudo console owner to another process */ - HANDLE new_owner =3D - OpenProcess (PROCESS_DUP_HANDLE, FALSE, switch_to); - HANDLE new_write_pipe =3D NULL; - HANDLE new_condrv_reference =3D NULL; - HANDLE new_conhost_process =3D NULL; - HANDLE new_pcon_in =3D NULL, new_pcon_out =3D NULL; - DuplicateHandle (GetCurrentProcess (), - ttyp->h_pcon_write_pipe, - new_owner, &new_write_pipe, - 0, TRUE, DUPLICATE_SAME_ACCESS); - DuplicateHandle (GetCurrentProcess (), - ttyp->h_pcon_condrv_reference, - new_owner, &new_condrv_reference, - 0, TRUE, DUPLICATE_SAME_ACCESS); - DuplicateHandle (GetCurrentProcess (), - ttyp->h_pcon_conhost_process, - new_owner, &new_conhost_process, - 0, TRUE, DUPLICATE_SAME_ACCESS); - DuplicateHandle (GetCurrentProcess (), ttyp->h_pcon_in, - new_owner, &new_pcon_in, - 0, TRUE, DUPLICATE_SAME_ACCESS); - DuplicateHandle (GetCurrentProcess (), ttyp->h_pcon_out, - new_owner, &new_pcon_out, - 0, TRUE, DUPLICATE_SAME_ACCESS); - CloseHandle (new_owner); - CloseHandle (ttyp->h_pcon_write_pipe); - CloseHandle (ttyp->h_pcon_condrv_reference); - CloseHandle (ttyp->h_pcon_conhost_process); - CloseHandle (ttyp->h_pcon_in); - CloseHandle (ttyp->h_pcon_out); - ttyp->pcon_pid =3D switch_to; - ttyp->h_pcon_write_pipe =3D new_write_pipe; - ttyp->h_pcon_condrv_reference =3D new_condrv_reference; - ttyp->h_pcon_conhost_process =3D new_conhost_process; - ttyp->h_pcon_in =3D new_pcon_in; - ttyp->h_pcon_out =3D new_pcon_out; - FreeConsole (); - pinfo p (myself->ppid); - if (!p || !AttachConsole (p->dwProcessId)) - AttachConsole (ATTACH_PARENT_PROCESS); - init_console_handler (false); - } - else - { /* Close pseudo console */ - FreeConsole (); - pinfo p (myself->ppid); - if (!p || !AttachConsole (p->dwProcessId)) - AttachConsole (ATTACH_PARENT_PROCESS); - init_console_handler (false); - /* Reconstruct pseudo console handler container here for close */ - HPCON_INTERNAL *hp =3D - (HPCON_INTERNAL *) HeapAlloc (GetProcessHeap (), 0, - sizeof (HPCON_INTERNAL)); - hp->hWritePipe =3D ttyp->h_pcon_write_pipe; - hp->hConDrvReference =3D ttyp->h_pcon_condrv_reference; - hp->hConHostProcess =3D ttyp->h_pcon_conhost_process; - /* HeapFree() will be called in ClosePseudoConsole() */ - ClosePseudoConsole ((HPCON) hp); - CloseHandle (ttyp->h_pcon_conhost_process); - ttyp->pcon_activated =3D false; - ttyp->switch_to_pcon_in =3D false; - ttyp->pcon_pid =3D 0; - ttyp->pcon_start =3D false; - ttyp->pcon_start_pid =3D 0; - } + /* Abandon the ownership of the nat pipe */ + ttyp->pcon_pid =3D 0; + ttyp->switch_to_pcon_in =3D false; } - else + } +} + +/* The function close_pseudoconsole() should be static so that it can + be called even after the fhandler_pty_slave instance is deleted. */ +void +fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to) +{ + DWORD switch_to =3D get_winpid_to_hand_over (ttyp, force_switch_to); + ttyp->previous_code_page =3D GetConsoleCP (); + ttyp->previous_output_code_page =3D GetConsoleOutputCP (); + if (pcon_pid_self (ttyp->pcon_pid)) + { /* I am owner of the nat pipe. */ + if (switch_to) { + /* Change pseudo console owner to another process (switch_to). */ + HANDLE new_owner =3D + OpenProcess (PROCESS_DUP_HANDLE, FALSE, switch_to); + HANDLE new_write_pipe =3D NULL; + HANDLE new_condrv_reference =3D NULL; + HANDLE new_conhost_process =3D NULL; + HANDLE new_pcon_in =3D NULL, new_pcon_out =3D NULL; + DuplicateHandle (GetCurrentProcess (), + ttyp->h_pcon_write_pipe, + new_owner, &new_write_pipe, + 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (GetCurrentProcess (), + ttyp->h_pcon_condrv_reference, + new_owner, &new_condrv_reference, + 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (GetCurrentProcess (), + ttyp->h_pcon_conhost_process, + new_owner, &new_conhost_process, + 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (GetCurrentProcess (), ttyp->h_pcon_in, + new_owner, &new_pcon_in, + 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle (GetCurrentProcess (), ttyp->h_pcon_out, + new_owner, &new_pcon_out, + 0, TRUE, DUPLICATE_SAME_ACCESS); + CloseHandle (new_owner); + CloseHandle (ttyp->h_pcon_write_pipe); + CloseHandle (ttyp->h_pcon_condrv_reference); + CloseHandle (ttyp->h_pcon_conhost_process); + CloseHandle (ttyp->h_pcon_in); + CloseHandle (ttyp->h_pcon_out); + ttyp->pcon_pid =3D switch_to; + ttyp->h_pcon_write_pipe =3D new_write_pipe; + ttyp->h_pcon_condrv_reference =3D new_condrv_reference; + ttyp->h_pcon_conhost_process =3D new_conhost_process; + ttyp->h_pcon_in =3D new_pcon_in; + ttyp->h_pcon_out =3D new_pcon_out; FreeConsole (); pinfo p (myself->ppid); if (!p || !AttachConsole (p->dwProcessId)) AttachConsole (ATTACH_PARENT_PROCESS); init_console_handler (false); } - } - else if (pcon_pid_self (ttyp->pcon_pid)) - { - if (switch_to) - ttyp->pcon_pid =3D switch_to; else - { - ttyp->pcon_pid =3D 0; + { /* Close pseudo console and abandon the ownership of the nat pipe. */ + FreeConsole (); + pinfo p (myself->ppid); + if (!p || !AttachConsole (p->dwProcessId)) + AttachConsole (ATTACH_PARENT_PROCESS); + init_console_handler (false); + /* Reconstruct pseudo console handler container here for close */ + HPCON_INTERNAL *hp =3D + (HPCON_INTERNAL *) HeapAlloc (GetProcessHeap (), 0, + sizeof (HPCON_INTERNAL)); + hp->hWritePipe =3D ttyp->h_pcon_write_pipe; + hp->hConDrvReference =3D ttyp->h_pcon_condrv_reference; + hp->hConHostProcess =3D ttyp->h_pcon_conhost_process; + /* HeapFree() will be called in ClosePseudoConsole() */ + ClosePseudoConsole ((HPCON) hp); + CloseHandle (ttyp->h_pcon_conhost_process); + ttyp->pcon_activated =3D false; ttyp->switch_to_pcon_in =3D false; + ttyp->pcon_pid =3D 0; + ttyp->pcon_start =3D false; + ttyp->pcon_start_pid =3D 0; } } + else + { /* Just detach from the pseudo console if I am not owner. */ + FreeConsole (); + pinfo p (myself->ppid); + if (!p || !AttachConsole (p->dwProcessId)) + AttachConsole (ATTACH_PARENT_PROCESS); + init_console_handler (false); + } } =20 static bool @@ -4032,10 +4022,22 @@ fhandler_pty_slave::setup_for_non_cygwin_app (bool = nopcon, PWCHAR envblock, if (disable_pcon || !term_has_pcon_cap (envblock)) nopcon =3D true; WaitForSingleObject (pcon_mutex, INFINITE); - bool enable_pcon =3D setup_pseudoconsole (nopcon); + /* Setting switch_to_pcon_in is necessary even if pseudo console + will not be activated. */ + fhandler_base *fh =3D ::cygheap->fdtab[0]; + if (fh && fh->get_major () =3D=3D DEV_PTYS_MAJOR) + { + fhandler_pty_slave *ptys =3D (fhandler_pty_slave *) fh; + ptys->get_ttyp ()->switch_to_pcon_in =3D true; + if (!pcon_pid_alive (ptys->get_ttyp ()->pcon_pid)) + ptys->get_ttyp ()->pcon_pid =3D myself->exec_dwProcessId; + } + bool pcon_enabled =3D false; + if (!nopcon) + pcon_enabled =3D setup_pseudoconsole (); ReleaseMutex (pcon_mutex); /* For pcon enabled case, transfer_input() is called in master::write() = */ - if (!enable_pcon && get_ttyp ()->getpgid () =3D=3D myself->pgid + if (!pcon_enabled && get_ttyp ()->getpgid () =3D=3D myself->pgid && stdin_is_ptys && get_ttyp ()->pcon_input_state_eq (tty::to_cyg)) { WaitForSingleObject (input_mutex, mutex_timeout); @@ -4047,7 +4049,8 @@ fhandler_pty_slave::setup_for_non_cygwin_app (bool no= pcon, PWCHAR envblock, =20 void fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp, - bool stdin_is_ptys) + bool stdin_is_ptys, + DWORD force_switch_to) { ttyp->wait_pcon_fwd (); if (ttyp->getpgid () =3D=3D myself->pgid && stdin_is_ptys @@ -4059,7 +4062,10 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (hand= le_set_t *p, tty *ttyp, ReleaseMutex (p->input_mutex); } WaitForSingleObject (p->pcon_mutex, INFINITE); - close_pseudoconsole (ttyp); + if (ttyp->pcon_activated) + close_pseudoconsole (ttyp, force_switch_to); + else + hand_over_only (ttyp, force_switch_to); ReleaseMutex (p->pcon_mutex); } =20 @@ -4123,14 +4129,17 @@ fhandler_pty_master::need_send_ctrl_c_event () } =20 void -fhandler_pty_slave::close_pseudoconsole_if_necessary (tty *ttyp, - fhandler_termios *fh) +fhandler_pty_slave::release_ownership_of_nat_pipe (tty *ttyp, + fhandler_termios *fh) { - if (fh->get_major () =3D=3D DEV_PTYM_MAJOR && ttyp->pcon_activated) + if (fh->get_major () =3D=3D DEV_PTYM_MAJOR) { fhandler_pty_master *ptym =3D (fhandler_pty_master *) fh; WaitForSingleObject (ptym->pcon_mutex, INFINITE); - close_pseudoconsole (ttyp); + if (ttyp->pcon_activated) + close_pseudoconsole (ttyp); + else + hand_over_only (ttyp); ReleaseMutex (ptym->pcon_mutex); } }