mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-22 00:38:06 +08:00
Cygwin: pty: Fix race issue in inheritance of pseudo console.
- If multiple non-cygwin processes are started/ended simultaneously, inheritance of pseudo console sometimes fails. This patch fixes the issue. Addresses: https://cygwin.com/pipermail/cygwin/2021-April/248292.html
This commit is contained in:
parent
b4fc81edcc
commit
bb93c6d7c2
@ -1072,6 +1072,24 @@ fhandler_pty_slave::set_switch_to_pcon (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static bool
|
||||||
|
pcon_pid_alive (DWORD pid)
|
||||||
|
{
|
||||||
|
if (pid == 0)
|
||||||
|
return false;
|
||||||
|
HANDLE h = OpenProcess (SYNCHRONIZE, FALSE, pid);
|
||||||
|
if (h == NULL)
|
||||||
|
return false;
|
||||||
|
CloseHandle (h);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static bool
|
||||||
|
pcon_pid_self (DWORD pid)
|
||||||
|
{
|
||||||
|
return (pid == myself->exec_dwProcessId);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fhandler_pty_slave::reset_switch_to_pcon (void)
|
fhandler_pty_slave::reset_switch_to_pcon (void)
|
||||||
{
|
{
|
||||||
@ -1153,17 +1171,8 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
|
|||||||
if (isHybrid)
|
if (isHybrid)
|
||||||
return;
|
return;
|
||||||
WaitForSingleObject (pcon_mutex, INFINITE);
|
WaitForSingleObject (pcon_mutex, INFINITE);
|
||||||
HANDLE h;
|
if (!pcon_pid_self (get_ttyp ()->pcon_pid)
|
||||||
if (get_ttyp ()->pcon_pid > MAX_PID &&
|
&& pcon_pid_alive (get_ttyp ()->pcon_pid))
|
||||||
(h = OpenProcess (SYNCHRONIZE, FALSE, get_ttyp ()->pcon_pid - MAX_PID)))
|
|
||||||
{
|
|
||||||
/* There is a process which is grabbing pseudo console. */
|
|
||||||
CloseHandle (h);
|
|
||||||
ReleaseMutex (pcon_mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (get_ttyp ()->pcon_pid && get_ttyp ()->pcon_pid != myself->pid
|
|
||||||
&& !!pinfo (get_ttyp ()->pcon_pid))
|
|
||||||
{
|
{
|
||||||
/* There is a process which is grabbing pseudo console. */
|
/* There is a process which is grabbing pseudo console. */
|
||||||
ReleaseMutex (pcon_mutex);
|
ReleaseMutex (pcon_mutex);
|
||||||
@ -1975,19 +1984,15 @@ fhandler_pty_common::resize_pseudo_console (struct winsize *ws)
|
|||||||
COORD size;
|
COORD size;
|
||||||
size.X = ws->ws_col;
|
size.X = ws->ws_col;
|
||||||
size.Y = ws->ws_row;
|
size.Y = ws->ws_row;
|
||||||
pinfo p (get_ttyp ()->pcon_pid);
|
HPCON_INTERNAL hpcon_local;
|
||||||
if (p)
|
HANDLE pcon_owner =
|
||||||
{
|
OpenProcess (PROCESS_DUP_HANDLE, FALSE, get_ttyp ()->pcon_pid);
|
||||||
HPCON_INTERNAL hpcon_local;
|
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_write_pipe,
|
||||||
HANDLE pcon_owner =
|
GetCurrentProcess (), &hpcon_local.hWritePipe,
|
||||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->exec_dwProcessId);
|
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_write_pipe,
|
ResizePseudoConsole ((HPCON) &hpcon_local, size);
|
||||||
GetCurrentProcess (), &hpcon_local.hWritePipe,
|
CloseHandle (pcon_owner);
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
CloseHandle (hpcon_local.hWritePipe);
|
||||||
ResizePseudoConsole ((HPCON) &hpcon_local, size);
|
|
||||||
CloseHandle (pcon_owner);
|
|
||||||
CloseHandle (hpcon_local.hWritePipe);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -3085,9 +3090,8 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
|||||||
{
|
{
|
||||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||||
ptys->get_ttyp ()->switch_to_pcon_in = true;
|
ptys->get_ttyp ()->switch_to_pcon_in = true;
|
||||||
if (ptys->get_ttyp ()->pcon_pid == 0
|
if (!pcon_pid_alive (ptys->get_ttyp ()->pcon_pid))
|
||||||
|| !pinfo (ptys->get_ttyp ()->pcon_pid))
|
ptys->get_ttyp ()->pcon_pid = myself->exec_dwProcessId;
|
||||||
ptys->get_ttyp ()->pcon_pid = myself->pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nopcon)
|
if (nopcon)
|
||||||
@ -3107,8 +3111,7 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
HANDLE hpConIn, hpConOut;
|
HANDLE hpConIn, hpConOut;
|
||||||
if (get_ttyp ()->pcon_pid && get_ttyp ()->pcon_pid != myself->pid
|
if (get_ttyp ()->pcon_activated)
|
||||||
&& !!pinfo (get_ttyp ()->pcon_pid) && get_ttyp ()->pcon_activated)
|
|
||||||
{
|
{
|
||||||
if (GetStdHandle (STD_INPUT_HANDLE) == get_handle ())
|
if (GetStdHandle (STD_INPUT_HANDLE) == get_handle ())
|
||||||
{ /* Send CSI6n just for requesting transfer input. */
|
{ /* Send CSI6n just for requesting transfer input. */
|
||||||
@ -3119,11 +3122,14 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
|||||||
get_ttyp ()->pcon_start_pid = myself->pid;
|
get_ttyp ()->pcon_start_pid = myself->pid;
|
||||||
WriteFile (get_output_handle (), "\033[6n", 4, &n, NULL);
|
WriteFile (get_output_handle (), "\033[6n", 4, &n, NULL);
|
||||||
ReleaseMutex (input_mutex);
|
ReleaseMutex (input_mutex);
|
||||||
|
while (get_ttyp ()->pcon_start)
|
||||||
|
Sleep (1);
|
||||||
}
|
}
|
||||||
/* Attach to the pseudo console which already exits. */
|
/* Attach to the pseudo console which already exits. */
|
||||||
pinfo p (get_ttyp ()->pcon_pid);
|
|
||||||
HANDLE pcon_owner =
|
HANDLE pcon_owner =
|
||||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->exec_dwProcessId);
|
OpenProcess (PROCESS_DUP_HANDLE, FALSE, get_ttyp ()->pcon_pid);
|
||||||
|
if (pcon_owner == NULL)
|
||||||
|
return false;
|
||||||
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
|
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
|
||||||
GetCurrentProcess (), &hpConIn,
|
GetCurrentProcess (), &hpConIn,
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
@ -3132,7 +3138,7 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
|||||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
CloseHandle (pcon_owner);
|
CloseHandle (pcon_owner);
|
||||||
FreeConsole ();
|
FreeConsole ();
|
||||||
AttachConsole (p->exec_dwProcessId);
|
AttachConsole (get_ttyp ()->pcon_pid);
|
||||||
goto skip_create;
|
goto skip_create;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3287,10 +3293,10 @@ skip_create:
|
|||||||
}
|
}
|
||||||
while (false);
|
while (false);
|
||||||
|
|
||||||
if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
|
if (!pcon_pid_alive (get_ttyp ()->pcon_pid))
|
||||||
get_ttyp ()->pcon_pid = myself->pid;
|
get_ttyp ()->pcon_pid = myself->exec_dwProcessId;
|
||||||
|
|
||||||
if (hpcon && get_ttyp ()->pcon_pid == myself->pid)
|
if (hpcon && pcon_pid_self (get_ttyp ()->pcon_pid))
|
||||||
{
|
{
|
||||||
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) hpcon;
|
HPCON_INTERNAL *hp = (HPCON_INTERNAL *) hpcon;
|
||||||
get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
|
get_ttyp ()->h_pcon_write_pipe = hp->hWritePipe;
|
||||||
@ -3381,15 +3387,14 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
|||||||
if (force_switch_to)
|
if (force_switch_to)
|
||||||
{
|
{
|
||||||
switch_to_stub = force_switch_to;
|
switch_to_stub = force_switch_to;
|
||||||
new_pcon_pid = force_switch_to + MAX_PID;
|
new_pcon_pid = force_switch_to;
|
||||||
ttyp->setpgid (new_pcon_pid);
|
ttyp->setpgid (force_switch_to + MAX_PID);
|
||||||
}
|
}
|
||||||
else if (ttyp->pcon_pid == myself->pid)
|
else if (pcon_pid_self (ttyp->pcon_pid))
|
||||||
{
|
{
|
||||||
/* Search another process which attaches to the pseudo console */
|
/* Search another process which attaches to the pseudo console */
|
||||||
DWORD current_pid = myself->exec_dwProcessId ?: myself->dwProcessId;
|
DWORD current_pid = myself->exec_dwProcessId ?: myself->dwProcessId;
|
||||||
switch_to =
|
switch_to = get_console_process_id (current_pid, false, true);
|
||||||
get_console_process_id (current_pid, false, true);
|
|
||||||
if (switch_to)
|
if (switch_to)
|
||||||
{
|
{
|
||||||
pinfo p (cygwin_pid (switch_to));
|
pinfo p (cygwin_pid (switch_to));
|
||||||
@ -3397,15 +3402,21 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
|||||||
{
|
{
|
||||||
if (p->exec_dwProcessId)
|
if (p->exec_dwProcessId)
|
||||||
switch_to_stub = p->exec_dwProcessId;
|
switch_to_stub = p->exec_dwProcessId;
|
||||||
new_pcon_pid = p->pid;
|
new_pcon_pid = p->exec_dwProcessId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch_to = get_console_process_id (current_pid, false, false);
|
||||||
|
if (switch_to)
|
||||||
|
new_pcon_pid = switch_to;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ttyp->pcon_activated)
|
if (ttyp->pcon_activated)
|
||||||
{
|
{
|
||||||
ttyp->previous_code_page = GetConsoleCP ();
|
ttyp->previous_code_page = GetConsoleCP ();
|
||||||
ttyp->previous_output_code_page = GetConsoleOutputCP ();
|
ttyp->previous_output_code_page = GetConsoleOutputCP ();
|
||||||
if (ttyp->pcon_pid == myself->pid)
|
if (pcon_pid_self (ttyp->pcon_pid))
|
||||||
{
|
{
|
||||||
switch_to = switch_to_stub ?: switch_to;
|
switch_to = switch_to_stub ?: switch_to;
|
||||||
if (switch_to)
|
if (switch_to)
|
||||||
@ -3447,6 +3458,15 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
|||||||
ttyp->h_pcon_conhost_process = new_conhost_process;
|
ttyp->h_pcon_conhost_process = new_conhost_process;
|
||||||
ttyp->h_pcon_in = new_pcon_in;
|
ttyp->h_pcon_in = new_pcon_in;
|
||||||
ttyp->h_pcon_out = new_pcon_out;
|
ttyp->h_pcon_out = new_pcon_out;
|
||||||
|
FreeConsole ();
|
||||||
|
pinfo p (myself->ppid);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
if (!AttachConsole (p->dwProcessId))
|
||||||
|
AttachConsole (ATTACH_PARENT_PROCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AttachConsole (ATTACH_PARENT_PROCESS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Close pseudo console */
|
{ /* Close pseudo console */
|
||||||
@ -3462,7 +3482,7 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
|||||||
/* Reconstruct pseudo console handler container here for close */
|
/* Reconstruct pseudo console handler container here for close */
|
||||||
HPCON_INTERNAL *hp =
|
HPCON_INTERNAL *hp =
|
||||||
(HPCON_INTERNAL *) HeapAlloc (GetProcessHeap (), 0,
|
(HPCON_INTERNAL *) HeapAlloc (GetProcessHeap (), 0,
|
||||||
sizeof (*hp));
|
sizeof (HPCON_INTERNAL));
|
||||||
hp->hWritePipe = ttyp->h_pcon_write_pipe;
|
hp->hWritePipe = ttyp->h_pcon_write_pipe;
|
||||||
hp->hConDrvReference = ttyp->h_pcon_condrv_reference;
|
hp->hConDrvReference = ttyp->h_pcon_condrv_reference;
|
||||||
hp->hConHostProcess = ttyp->h_pcon_conhost_process;
|
hp->hConHostProcess = ttyp->h_pcon_conhost_process;
|
||||||
@ -3489,7 +3509,7 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
|
|||||||
AttachConsole (ATTACH_PARENT_PROCESS);
|
AttachConsole (ATTACH_PARENT_PROCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ttyp->pcon_pid == myself->pid)
|
else if (pcon_pid_self (ttyp->pcon_pid))
|
||||||
{
|
{
|
||||||
if (switch_to_stub)
|
if (switch_to_stub)
|
||||||
ttyp->pcon_pid = new_pcon_pid;
|
ttyp->pcon_pid = new_pcon_pid;
|
||||||
|
@ -327,25 +327,18 @@ tty_min::setpgid (int pid)
|
|||||||
&& ttyp->pcon_input_state_eq (tty::to_nat))
|
&& ttyp->pcon_input_state_eq (tty::to_nat))
|
||||||
{
|
{
|
||||||
bool attach_restore = false;
|
bool attach_restore = false;
|
||||||
DWORD pcon_winpid = 0;
|
|
||||||
if (ttyp->pcon_pid)
|
|
||||||
{
|
|
||||||
pinfo p (ttyp->pcon_pid);
|
|
||||||
if (p)
|
|
||||||
pcon_winpid = p->exec_dwProcessId ?: p->dwProcessId;
|
|
||||||
}
|
|
||||||
HANDLE from = ptys->get_handle_nat ();
|
HANDLE from = ptys->get_handle_nat ();
|
||||||
if (ttyp->pcon_activated && pcon_winpid
|
if (ttyp->pcon_activated && ttyp->pcon_pid
|
||||||
&& !ptys->get_console_process_id (pcon_winpid, true))
|
&& !ptys->get_console_process_id (ttyp->pcon_pid, true))
|
||||||
{
|
{
|
||||||
HANDLE pcon_owner =
|
HANDLE pcon_owner =
|
||||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, pcon_winpid);
|
OpenProcess (PROCESS_DUP_HANDLE, FALSE, ttyp->pcon_pid);
|
||||||
DuplicateHandle (pcon_owner, ttyp->h_pcon_in,
|
DuplicateHandle (pcon_owner, ttyp->h_pcon_in,
|
||||||
GetCurrentProcess (), &from,
|
GetCurrentProcess (), &from,
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
CloseHandle (pcon_owner);
|
CloseHandle (pcon_owner);
|
||||||
FreeConsole ();
|
FreeConsole ();
|
||||||
AttachConsole (pcon_winpid);
|
AttachConsole (ttyp->pcon_pid);
|
||||||
attach_restore = true;
|
attach_restore = true;
|
||||||
}
|
}
|
||||||
WaitForSingleObject (ptys->input_mutex, INFINITE);
|
WaitForSingleObject (ptys->input_mutex, INFINITE);
|
||||||
|
@ -113,7 +113,7 @@ private:
|
|||||||
bool pcon_start;
|
bool pcon_start;
|
||||||
pid_t pcon_start_pid;
|
pid_t pcon_start_pid;
|
||||||
bool switch_to_pcon_in;
|
bool switch_to_pcon_in;
|
||||||
pid_t pcon_pid;
|
DWORD pcon_pid;
|
||||||
UINT term_code_page;
|
UINT term_code_page;
|
||||||
DWORD pcon_last_time;
|
DWORD pcon_last_time;
|
||||||
HANDLE h_pcon_write_pipe;
|
HANDLE h_pcon_write_pipe;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user