Cygwin: pty: Fix state management for pseudo console support.

- Pseudo console support introduced by commit
  169d65a577 has some bugs which
  cause mismatch between state variables and real pseudo console
  state regarding console attaching and r/w pipe switching. This
  patch fixes this issue by redesigning the state management.
This commit is contained in:
Takashi Yano
2019-09-04 10:45:35 +09:00
committed by Corinna Vinschen
parent ffbb9b4971
commit 583102e7c9
6 changed files with 290 additions and 255 deletions

View File

@ -578,53 +578,62 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
pidRestore = fhandler_console::get_console_process_id
(GetCurrentProcessId (), false);
fhandler_pty_slave *ptys = NULL;
for (int fd = 0; fd < 3; fd ++)
int chk_order[] = {1, 0, 2};
for (int i = 0; i < 3; i ++)
{
int fd = chk_order[i];
fhandler_base *fh = ::cygheap->fdtab[fd];
if (fh && fh->get_major () == DEV_PTYS_MAJOR)
{
ptys = (fhandler_pty_slave *) fh;
if (ptys->getPseudoConsole () &&
!fhandler_console::get_console_process_id (
ptys->getHelperProcessId (), true))
if (ptys->getPseudoConsole ())
{
DWORD dwHelperProcessId = ptys->getHelperProcessId ();
debug_printf ("found a PTY slave %d: helper_PID=%d",
fh->get_minor (), dwHelperProcessId);
FreeConsole ();
if (!AttachConsole (dwHelperProcessId))
fh->get_minor (), dwHelperProcessId);
if (fhandler_console::get_console_process_id
(dwHelperProcessId, true))
{
/* Fallback */
DWORD target[3] = {
STD_INPUT_HANDLE,
STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE
};
if (fd == 0)
{
ptys->set_handle (ptys->get_handle_cyg ());
SetStdHandle (target[fd],
ptys->get_handle ());
}
else
{
ptys->set_output_handle (
ptys->get_output_handle_cyg ());
SetStdHandle (target[fd],
ptys->get_output_handle ());
}
/* Already attached */
attach_to_pcon = true;
break;
}
else
{
init_console_handler (true);
attach_to_pcon = true;
break;
FreeConsole ();
if (AttachConsole (dwHelperProcessId))
{
attach_to_pcon = true;
break;
}
else
{
/* Fallback */
DWORD target[3] = {
STD_INPUT_HANDLE,
STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE
};
if (fd == 0)
{
ptys->set_handle (ptys->get_handle_cyg ());
SetStdHandle (target[fd],
ptys->get_handle ());
}
else if (fd < 3)
{
ptys->set_output_handle (
ptys->get_output_handle_cyg ());
SetStdHandle (target[fd],
ptys->get_output_handle ());
}
}
}
}
}
}
if (ptys)
ptys->fixup_after_attach (true);
ptys->fixup_after_attach (!iscygwin ());
loop:
/* When ruid != euid we create the new process under the current original