Cygwin: pty: Encapsulate pty code in tty::setpgid().

- This patch hides complex pty codes in tty::setpgid() to transfer
  input into the class fhandler_pty_slave by encapsulating it.
This commit is contained in:
Takashi Yano 2022-02-21 22:40:48 +09:00
parent 0ddf19d6ca
commit 054b00d96a
3 changed files with 55 additions and 58 deletions

View File

@ -1956,6 +1956,7 @@ class fhandler_termios: public fhandler_base
static bool path_iscygexec_w (LPCWSTR n, LPWSTR c);
virtual bool is_pty_master_with_pcon () { return false; }
virtual void cleanup_before_exit () {}
virtual void setpgid_aux (pid_t pid) {}
};
enum ansi_intensity
@ -2400,6 +2401,7 @@ class fhandler_pty_slave: public fhandler_pty_common
bool stdin_is_ptys);
static void cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
bool stdin_is_ptys);
void setpgid_aux (pid_t pid);
};
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))

View File

@ -4047,3 +4047,54 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
close_pseudoconsole (ttyp);
ReleaseMutex (p->pcon_mutex);
}
void
fhandler_pty_slave::setpgid_aux (pid_t pid)
{
WaitForSingleObject (pcon_mutex, INFINITE);
bool was_pcon_fg = get_ttyp ()->pcon_fg (tc ()->pgid);
bool pcon_fg = get_ttyp ()->pcon_fg (pid);
if (!was_pcon_fg && pcon_fg && get_ttyp ()->switch_to_pcon_in
&& 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);
}
else if (was_pcon_fg && !pcon_fg && get_ttyp ()->switch_to_pcon_in
&& get_ttyp ()->pcon_input_state_eq (tty::to_nat))
{
bool attach_restore = false;
HANDLE from = get_handle_nat ();
if (get_ttyp ()->pcon_activated && get_ttyp ()->pcon_pid
&& !get_console_process_id (get_ttyp ()->pcon_pid, true))
{
HANDLE pcon_owner =
OpenProcess (PROCESS_DUP_HANDLE, FALSE, get_ttyp ()->pcon_pid);
DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
GetCurrentProcess (), &from,
0, TRUE, DUPLICATE_SAME_ACCESS);
CloseHandle (pcon_owner);
FreeConsole ();
AttachConsole (get_ttyp ()->pcon_pid);
attach_restore = true;
}
WaitForSingleObject (input_mutex, mutex_timeout);
transfer_input (tty::to_cyg, from, get_ttyp (), input_available_event);
ReleaseMutex (input_mutex);
if (attach_restore)
{
FreeConsole ();
pinfo p (myself->ppid);
if (p)
{
if (!AttachConsole (p->dwProcessId))
AttachConsole (ATTACH_PARENT_PROCESS);
}
else
AttachConsole (ATTACH_PARENT_PROCESS);
}
}
ReleaseMutex (pcon_mutex);
}

View File

@ -306,65 +306,9 @@ extern DWORD mutex_timeout; /* defined in fhandler_termios.cc */
void
tty_min::setpgid (int pid)
{
fhandler_pty_slave *ptys = NULL;
cygheap_fdenum cfd (false);
while (cfd.next () >= 0 && ptys == NULL)
if (cfd->get_device () == getntty ()
&& cfd->get_major () == DEV_PTYS_MAJOR)
ptys = (fhandler_pty_slave *) (fhandler_base *) cfd;
if (::cygheap->ctty)
::cygheap->ctty->setpgid_aux (pid);
if (ptys)
{
tty *ttyp = (tty *) ptys->tc ();
WaitForSingleObject (ptys->pcon_mutex, INFINITE);
bool was_pcon_fg = ttyp->pcon_fg (pgid);
bool pcon_fg = ttyp->pcon_fg (pid);
if (!was_pcon_fg && pcon_fg && ttyp->switch_to_pcon_in
&& ttyp->pcon_input_state_eq (tty::to_cyg))
{
WaitForSingleObject (ptys->input_mutex, mutex_timeout);
fhandler_pty_slave::transfer_input (tty::to_nat,
ptys->get_handle (), ttyp,
ptys->get_input_available_event ());
ReleaseMutex (ptys->input_mutex);
}
else if (was_pcon_fg && !pcon_fg && ttyp->switch_to_pcon_in
&& ttyp->pcon_input_state_eq (tty::to_nat))
{
bool attach_restore = false;
HANDLE from = ptys->get_handle_nat ();
if (ttyp->pcon_activated && ttyp->pcon_pid
&& !ptys->get_console_process_id (ttyp->pcon_pid, true))
{
HANDLE pcon_owner =
OpenProcess (PROCESS_DUP_HANDLE, FALSE, ttyp->pcon_pid);
DuplicateHandle (pcon_owner, ttyp->h_pcon_in,
GetCurrentProcess (), &from,
0, TRUE, DUPLICATE_SAME_ACCESS);
CloseHandle (pcon_owner);
FreeConsole ();
AttachConsole (ttyp->pcon_pid);
attach_restore = true;
}
WaitForSingleObject (ptys->input_mutex, mutex_timeout);
fhandler_pty_slave::transfer_input (tty::to_cyg, from, ttyp,
ptys->get_input_available_event ());
ReleaseMutex (ptys->input_mutex);
if (attach_restore)
{
FreeConsole ();
pinfo p (myself->ppid);
if (p)
{
if (!AttachConsole (p->dwProcessId))
AttachConsole (ATTACH_PARENT_PROCESS);
}
else
AttachConsole (ATTACH_PARENT_PROCESS);
}
}
ReleaseMutex (ptys->pcon_mutex);
}
pgid = pid;
}