4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-03-02 21:15:27 +08:00

Cygwin: pty: Add missing input transfer when switch_to_pcon_in state.

- This patch fixes the bug that input is wrongly sent to io_handle_nat
  rather than io_handle when neither read() nor select() is called
  after the cygwin app is started from non-cygwin app. This happens
  only if psuedo console is disabled.

Addresses:
  https://cygwin.com/pipermail/cygwin-patches/2021q4/011587.html
This commit is contained in:
Takashi Yano 2021-12-11 22:08:25 +09:00
parent c2f39a543e
commit c54b890bc7
2 changed files with 75 additions and 17 deletions

View File

@ -1077,11 +1077,15 @@ pcon_pid_alive (DWORD pid)
{ {
if (pid == 0) if (pid == 0)
return false; return false;
HANDLE h = OpenProcess (SYNCHRONIZE, FALSE, pid); HANDLE h = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (h == NULL) if (h == NULL)
return false; return false;
DWORD exit_code;
BOOL r = GetExitCodeProcess (h, &exit_code);
CloseHandle (h); CloseHandle (h);
if (r && exit_code == STILL_ACTIVE)
return true; return true;
return false;
} }
inline static bool inline static bool
@ -1172,11 +1176,53 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
return; return;
if (get_ttyp ()->pcon_start) if (get_ttyp ()->pcon_start)
return; return;
/* This input transfer is needed if non-cygwin app is terminated
by Ctrl-C or killed. */
WaitForSingleObject (input_mutex, INFINITE);
if (!get_ttyp ()->pcon_fg (get_ttyp ()->getpgid ())
&& get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->pcon_activated
&& get_ttyp ()->pcon_input_state_eq (tty::to_nat))
transfer_input (tty::to_cyg, get_handle_nat (), get_ttyp (),
input_available_event);
ReleaseMutex (input_mutex);
WaitForSingleObject (pcon_mutex, INFINITE); WaitForSingleObject (pcon_mutex, INFINITE);
if (!pcon_pid_self (get_ttyp ()->pcon_pid) if (!pcon_pid_self (get_ttyp ()->pcon_pid)
&& pcon_pid_alive (get_ttyp ()->pcon_pid)) && pcon_pid_alive (get_ttyp ()->pcon_pid))
{ {
/* There is a process which is grabbing pseudo console. */ /* There is a process which is grabbing pseudo console. */
if (get_ttyp ()->pcon_activated
&& get_ttyp ()->pcon_input_state_eq (tty::to_nat))
{
HANDLE pcon_owner =
OpenProcess (PROCESS_DUP_HANDLE, FALSE, get_ttyp ()->pcon_pid);
if (pcon_owner)
{
pinfo pinfo_resume = pinfo (myself->ppid);
DWORD resume_pid;
if (pinfo_resume)
resume_pid = pinfo_resume->dwProcessId;
else
resume_pid =
get_console_process_id (myself->dwProcessId, false);
if (resume_pid)
{
HANDLE h_pcon_in;
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
GetCurrentProcess (), &h_pcon_in,
0, TRUE, DUPLICATE_SAME_ACCESS);
FreeConsole ();
AttachConsole (get_ttyp ()->pcon_pid);
WaitForSingleObject (input_mutex, INFINITE);
transfer_input (tty::to_cyg, h_pcon_in, get_ttyp (),
input_available_event);
ReleaseMutex (input_mutex);
FreeConsole ();
AttachConsole (resume_pid);
CloseHandle (h_pcon_in);
}
CloseHandle (pcon_owner);
}
}
ReleaseMutex (pcon_mutex); ReleaseMutex (pcon_mutex);
return; return;
} }
@ -1231,6 +1277,7 @@ fhandler_pty_slave::mask_switch_to_pcon_in (bool mask, bool xfer)
HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name); HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name);
CloseHandle (masked); CloseHandle (masked);
WaitForSingleObject (input_mutex, INFINITE);
if (mask) if (mask)
{ {
if (InterlockedIncrement (&num_reader) == 1) if (InterlockedIncrement (&num_reader) == 1)
@ -1239,28 +1286,26 @@ fhandler_pty_slave::mask_switch_to_pcon_in (bool mask, bool xfer)
else if (InterlockedDecrement (&num_reader) == 0) else if (InterlockedDecrement (&num_reader) == 0)
CloseHandle (slave_reading); CloseHandle (slave_reading);
/* This is needed when cygwin-app is started from non-cygwin app if
pseudo console is disabled. */
bool need_xfer = get_ttyp ()->pcon_fg (get_ttyp ()->getpgid ()) && mask
&& get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->pcon_activated;
/* In GDB, transfer input based on setpgid() does not work because /* In GDB, transfer input based on setpgid() does not work because
GDB may not set terminal process group properly. Therefore, GDB may not set terminal process group properly. Therefore,
transfer input here if isHybrid is set. */ transfer input here if isHybrid is set. */
if (isHybrid && !!masked != mask && xfer if ((isHybrid || need_xfer) && !!masked != mask && xfer
&& GetStdHandle (STD_INPUT_HANDLE) == get_handle ()) && GetStdHandle (STD_INPUT_HANDLE) == get_handle ())
{ {
if (mask && get_ttyp ()->pcon_input_state_eq (tty::to_nat)) if (mask && get_ttyp ()->pcon_input_state_eq (tty::to_nat))
{
WaitForSingleObject (input_mutex, INFINITE);
transfer_input (tty::to_cyg, get_handle_nat (), get_ttyp (), transfer_input (tty::to_cyg, get_handle_nat (), get_ttyp (),
input_available_event); input_available_event);
ReleaseMutex (input_mutex);
}
else if (!mask && get_ttyp ()->pcon_input_state_eq (tty::to_cyg)) else if (!mask && get_ttyp ()->pcon_input_state_eq (tty::to_cyg))
{
WaitForSingleObject (input_mutex, INFINITE);
transfer_input (tty::to_nat, get_handle (), get_ttyp (), transfer_input (tty::to_nat, get_handle (), get_ttyp (),
input_available_event); input_available_event);
}
ReleaseMutex (input_mutex); ReleaseMutex (input_mutex);
} }
}
}
bool bool
fhandler_pty_master::to_be_read_from_pcon (void) fhandler_pty_master::to_be_read_from_pcon (void)
@ -1536,7 +1581,7 @@ out:
if (ptr0) if (ptr0)
{ /* Not tcflush() */ { /* Not tcflush() */
bool saw_eol = totalread > 0 && strchr ("\r\n", ptr0[totalread -1]); bool saw_eol = totalread > 0 && strchr ("\r\n", ptr0[totalread -1]);
mask_switch_to_pcon_in (false, saw_eol); mask_switch_to_pcon_in (false, saw_eol || len == 0);
} }
} }
@ -2187,6 +2232,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
/* Write terminal input to to_slave_nat pipe instead of output_handle /* Write terminal input to to_slave_nat pipe instead of output_handle
if current application is native console application. */ if current application is native console application. */
WaitForSingleObject (input_mutex, INFINITE);
if (to_be_read_from_pcon () && get_ttyp ()->pcon_activated if (to_be_read_from_pcon () && get_ttyp ()->pcon_activated
&& get_ttyp ()->pcon_input_state == tty::to_nat) && get_ttyp ()->pcon_input_state == tty::to_nat)
{ {
@ -2203,7 +2249,6 @@ fhandler_pty_master::write (const void *ptr, size_t len)
&mbp); &mbp);
} }
WaitForSingleObject (input_mutex, INFINITE);
if ((ti.c_lflag & ISIG) && !(ti.c_lflag & NOFLSH) if ((ti.c_lflag & ISIG) && !(ti.c_lflag & NOFLSH)
&& memchr (buf, '\003', nlen)) && memchr (buf, '\003', nlen))
get_ttyp ()->discard_input = true; get_ttyp ()->discard_input = true;
@ -2214,6 +2259,14 @@ fhandler_pty_master::write (const void *ptr, size_t len)
return len; return len;
} }
/* This input transfer is needed when cygwin-app which is started from
non-cygwin app is terminated if pseudo console is disabled. */
if (to_be_read_from_pcon () && !get_ttyp ()->pcon_activated
&& get_ttyp ()->pcon_input_state == tty::to_cyg)
fhandler_pty_slave::transfer_input (tty::to_nat, from_master,
get_ttyp (), input_available_event);
ReleaseMutex (input_mutex);
line_edit_status status = line_edit (p, len, ti, &ret); line_edit_status status = line_edit (p, len, ti, &ret);
if (status > line_edit_signalled && status != line_edit_pipe_full) if (status > line_edit_signalled && status != line_edit_pipe_full)
ret = -1; ret = -1;

View File

@ -9,3 +9,8 @@ Bug Fixes
This solves the following issues: This solves the following issues:
Addresses: https://cygwin.com/pipermail/cygwin/2021-November/250087.html Addresses: https://cygwin.com/pipermail/cygwin/2021-November/250087.html
https://cygwin.com/pipermail/cygwin/2021-December/250103.html https://cygwin.com/pipermail/cygwin/2021-December/250103.html
- Fix a bug in pty code that input is wrongly sent to io_handle_nat
rather than io_handle while neither read() nor select() is called
after the cygwin app is started from non-cygwin app.
Addresses: https://cygwin.com/pipermail/cygwin-patches/2021q4/011587.html