4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-19 12:59:21 +08:00

Cygwin: pty: Avoid deadlock when pcon is started on console.

- Previously, "env SHELL=cmd script" command in console caused
  deadlock when starting cmd.exe. This patch fixes the issue.
This commit is contained in:
Takashi Yano 2022-05-09 00:19:47 +09:00
parent aea6940043
commit cc94490f6e
2 changed files with 17 additions and 19 deletions

View File

@ -1171,11 +1171,7 @@ fhandler_pty_slave::reset_switch_to_nat_pipe (void)
bool need_restore_handles = get_ttyp ()->pcon_activated; bool need_restore_handles = get_ttyp ()->pcon_activated;
WaitForSingleObject (pipe_sw_mutex, INFINITE); WaitForSingleObject (pipe_sw_mutex, INFINITE);
if (get_ttyp ()->pcon_activated) if (get_ttyp ()->pcon_activated)
{
acquire_attach_mutex (mutex_timeout);
close_pseudoconsole (get_ttyp ()); close_pseudoconsole (get_ttyp ());
release_attach_mutex ();
}
else else
hand_over_only (get_ttyp ()); hand_over_only (get_ttyp ());
ReleaseMutex (pipe_sw_mutex); ReleaseMutex (pipe_sw_mutex);
@ -3244,9 +3240,11 @@ fhandler_pty_slave::setup_pseudoconsole ()
GetCurrentProcess (), &hpConOut, GetCurrentProcess (), &hpConOut,
0, TRUE, DUPLICATE_SAME_ACCESS); 0, TRUE, DUPLICATE_SAME_ACCESS);
CloseHandle (pcon_owner); CloseHandle (pcon_owner);
acquire_attach_mutex (mutex_timeout);
FreeConsole (); FreeConsole ();
AttachConsole (get_ttyp ()->nat_pipe_owner_pid); AttachConsole (get_ttyp ()->nat_pipe_owner_pid);
init_console_handler (false); init_console_handler (false);
release_attach_mutex ();
goto skip_create; goto skip_create;
} }
@ -3368,9 +3366,11 @@ fhandler_pty_slave::setup_pseudoconsole ()
HeapFree (GetProcessHeap (), 0, si.lpAttributeList); HeapFree (GetProcessHeap (), 0, si.lpAttributeList);
/* Attach to pseudo console */ /* Attach to pseudo console */
acquire_attach_mutex (mutex_timeout);
FreeConsole (); FreeConsole ();
AttachConsole (pi.dwProcessId); AttachConsole (pi.dwProcessId);
init_console_handler (false); init_console_handler (false);
release_attach_mutex ();
/* Terminate helper process */ /* Terminate helper process */
SetEvent (goodbye); SetEvent (goodbye);
@ -3535,8 +3535,10 @@ void
fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to) fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
{ {
DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to); DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
acquire_attach_mutex (mutex_timeout);
ttyp->previous_code_page = GetConsoleCP (); ttyp->previous_code_page = GetConsoleCP ();
ttyp->previous_output_code_page = GetConsoleOutputCP (); ttyp->previous_output_code_page = GetConsoleOutputCP ();
release_attach_mutex ();
if (nat_pipe_owner_self (ttyp->nat_pipe_owner_pid)) if (nat_pipe_owner_self (ttyp->nat_pipe_owner_pid))
{ /* I am owner of the nat pipe. */ { /* I am owner of the nat pipe. */
if (switch_to) if (switch_to)
@ -3578,19 +3580,23 @@ 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;
acquire_attach_mutex (mutex_timeout);
FreeConsole (); FreeConsole ();
pinfo p (myself->ppid); pinfo p (myself->ppid);
if (!p || !AttachConsole (p->dwProcessId)) if (!p || !AttachConsole (p->dwProcessId))
AttachConsole (ATTACH_PARENT_PROCESS); AttachConsole (ATTACH_PARENT_PROCESS);
init_console_handler (false); init_console_handler (false);
release_attach_mutex ();
} }
else else
{ /* Close pseudo console and abandon the ownership of the nat pipe. */ { /* Close pseudo console and abandon the ownership of the nat pipe. */
acquire_attach_mutex (mutex_timeout);
FreeConsole (); FreeConsole ();
pinfo p (myself->ppid); pinfo p (myself->ppid);
if (!p || !AttachConsole (p->dwProcessId)) if (!p || !AttachConsole (p->dwProcessId))
AttachConsole (ATTACH_PARENT_PROCESS); AttachConsole (ATTACH_PARENT_PROCESS);
init_console_handler (false); init_console_handler (false);
release_attach_mutex ();
/* 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,
@ -3610,11 +3616,13 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
} }
else else
{ /* Just detach from the pseudo console if I am not owner. */ { /* Just detach from the pseudo console if I am not owner. */
acquire_attach_mutex (mutex_timeout);
FreeConsole (); FreeConsole ();
pinfo p (myself->ppid); pinfo p (myself->ppid);
if (!p || !AttachConsole (p->dwProcessId)) if (!p || !AttachConsole (p->dwProcessId))
AttachConsole (ATTACH_PARENT_PROCESS); AttachConsole (ATTACH_PARENT_PROCESS);
init_console_handler (false); init_console_handler (false);
release_attach_mutex ();
} }
} }
@ -4040,11 +4048,7 @@ fhandler_pty_slave::setup_for_non_cygwin_app (bool nopcon, PWCHAR envblock,
} }
bool pcon_enabled = false; bool pcon_enabled = false;
if (!nopcon) if (!nopcon)
{
acquire_attach_mutex (mutex_timeout);
pcon_enabled = setup_pseudoconsole (); pcon_enabled = setup_pseudoconsole ();
release_attach_mutex ();
}
ReleaseMutex (pipe_sw_mutex); ReleaseMutex (pipe_sw_mutex);
/* For pcon enabled case, transfer_input() is called in master::write() */ /* For pcon enabled case, transfer_input() is called in master::write() */
if (!pcon_enabled && get_ttyp ()->getpgid () == myself->pgid if (!pcon_enabled && get_ttyp ()->getpgid () == myself->pgid
@ -4077,11 +4081,7 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
} }
WaitForSingleObject (p->pipe_sw_mutex, INFINITE); WaitForSingleObject (p->pipe_sw_mutex, INFINITE);
if (ttyp->pcon_activated) if (ttyp->pcon_activated)
{
acquire_attach_mutex (mutex_timeout);
close_pseudoconsole (ttyp, force_switch_to); close_pseudoconsole (ttyp, force_switch_to);
release_attach_mutex ();
}
else else
hand_over_only (ttyp, force_switch_to); hand_over_only (ttyp, force_switch_to);
ReleaseMutex (p->pipe_sw_mutex); ReleaseMutex (p->pipe_sw_mutex);
@ -4111,6 +4111,7 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
bool attach_restore = false; bool attach_restore = false;
HANDLE from = get_handle_nat (); HANDLE from = get_handle_nat ();
DWORD resume_pid = 0; DWORD resume_pid = 0;
WaitForSingleObject (input_mutex, mutex_timeout);
if (get_ttyp ()->pcon_activated && get_ttyp ()->nat_pipe_owner_pid if (get_ttyp ()->pcon_activated && get_ttyp ()->nat_pipe_owner_pid
&& !get_console_process_id (get_ttyp ()->nat_pipe_owner_pid, true)) && !get_console_process_id (get_ttyp ()->nat_pipe_owner_pid, true))
{ {
@ -4126,13 +4127,12 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
} }
else else
acquire_attach_mutex (mutex_timeout); acquire_attach_mutex (mutex_timeout);
WaitForSingleObject (input_mutex, mutex_timeout);
transfer_input (tty::to_cyg, from, get_ttyp (), input_available_event); transfer_input (tty::to_cyg, from, get_ttyp (), input_available_event);
ReleaseMutex (input_mutex);
if (attach_restore) if (attach_restore)
resume_from_temporarily_attach (resume_pid); resume_from_temporarily_attach (resume_pid);
else else
release_attach_mutex (); release_attach_mutex ();
ReleaseMutex (input_mutex);
} }
ReleaseMutex (pipe_sw_mutex); ReleaseMutex (pipe_sw_mutex);
} }

View File

@ -1125,7 +1125,6 @@ peek_console (select_record *me, bool)
{ {
if (fh->bg_check (SIGTTIN, true) <= bg_eof) if (fh->bg_check (SIGTTIN, true) <= bg_eof)
{ {
release_attach_mutex ();
fh->release_input_mutex (); fh->release_input_mutex ();
return me->read_ready = true; return me->read_ready = true;
} }
@ -1142,7 +1141,6 @@ peek_console (select_record *me, bool)
&& global_sigs[SIGWINCH].sa_handler != SIG_DFL) && global_sigs[SIGWINCH].sa_handler != SIG_DFL)
{ {
set_sig_errno (EINTR); set_sig_errno (EINTR);
release_attach_mutex ();
fh->release_input_mutex (); fh->release_input_mutex ();
return -1; return -1;
} }