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:
parent
ffbb9b4971
commit
583102e7c9
|
@ -147,18 +147,16 @@ dtable::get_debugger_info ()
|
|||
void
|
||||
dtable::stdio_init ()
|
||||
{
|
||||
bool need_fixup_handle = false;
|
||||
fhandler_pty_slave *ptys = NULL;
|
||||
bool is_pty[3] = {false, false, false};
|
||||
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;
|
||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||
if (ptys->getPseudoConsole ())
|
||||
{
|
||||
is_pty[fd] = true;
|
||||
bool attached = !!fhandler_console::get_console_process_id
|
||||
(ptys->getHelperProcessId (), true);
|
||||
if (!attached)
|
||||
|
@ -167,15 +165,12 @@ dtable::stdio_init ()
|
|||
by some reason. This happens if the executable is
|
||||
a windows GUI binary, such as mintty. */
|
||||
FreeConsole ();
|
||||
AttachConsole (ptys->getHelperProcessId ());
|
||||
need_fixup_handle = true;
|
||||
if (AttachConsole (ptys->getHelperProcessId ()))
|
||||
break;
|
||||
}
|
||||
ptys->reset_switch_to_pcon ();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_fixup_handle)
|
||||
goto fixup_handle;
|
||||
|
||||
if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
|
||||
{
|
||||
|
@ -185,27 +180,6 @@ dtable::stdio_init ()
|
|||
return;
|
||||
}
|
||||
|
||||
fixup_handle:
|
||||
if (need_fixup_handle)
|
||||
{
|
||||
HANDLE h;
|
||||
h = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, 0, 0);
|
||||
if (is_pty[0])
|
||||
{
|
||||
SetStdHandle (STD_INPUT_HANDLE, h);
|
||||
ptys->set_handle (h);
|
||||
}
|
||||
h = CreateFile ("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, 0);
|
||||
if (is_pty[1])
|
||||
SetStdHandle (STD_OUTPUT_HANDLE, h);
|
||||
if (is_pty[2])
|
||||
SetStdHandle (STD_ERROR_HANDLE, h);
|
||||
if (is_pty[1] || is_pty[2])
|
||||
ptys->set_output_handle (h);
|
||||
}
|
||||
|
||||
HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
|
||||
HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
|
||||
|
|
|
@ -2106,19 +2106,22 @@ class fhandler_pty_common: public fhandler_termios
|
|||
protected:
|
||||
BOOL process_opost_output (HANDLE h,
|
||||
const void *ptr, ssize_t& len, bool is_echo);
|
||||
bool check_switch_to_pcon (void);
|
||||
};
|
||||
|
||||
class fhandler_pty_slave: public fhandler_pty_common
|
||||
{
|
||||
HANDLE inuse; // used to indicate that a tty is in use
|
||||
HANDLE output_handle_cyg, io_handle_cyg;
|
||||
DWORD pid_restore;
|
||||
|
||||
/* Helper functions for fchmod and fchown. */
|
||||
bool fch_open_handles (bool chown);
|
||||
int fch_set_sd (security_descriptor &sd, bool chown);
|
||||
void fch_close_handles ();
|
||||
|
||||
bool try_reattach_pcon ();
|
||||
void restore_reattach_pcon ();
|
||||
|
||||
public:
|
||||
/* Constructor */
|
||||
fhandler_pty_slave (int);
|
||||
|
@ -2172,7 +2175,6 @@ class fhandler_pty_slave: public fhandler_pty_common
|
|||
void set_switch_to_pcon (void);
|
||||
void reset_switch_to_pcon (void);
|
||||
void push_to_pcon_screenbuffer (const char *ptr, size_t len);
|
||||
bool has_master_opened (void);
|
||||
void mask_switch_to_pcon (bool mask)
|
||||
{
|
||||
get_ttyp ()->mask_switch_to_pcon = mask;
|
||||
|
|
|
@ -3136,16 +3136,29 @@ DWORD
|
|||
fhandler_console::get_console_process_id (DWORD pid, bool match)
|
||||
{
|
||||
DWORD tmp;
|
||||
int num = GetConsoleProcessList (&tmp, 1);
|
||||
DWORD *list = (DWORD *)
|
||||
HeapAlloc (GetProcessHeap (), 0, num * sizeof (DWORD));
|
||||
num = GetConsoleProcessList (list, num);
|
||||
DWORD num, num_req;
|
||||
num = 1;
|
||||
num_req = GetConsoleProcessList (&tmp, num);
|
||||
DWORD *list;
|
||||
while (true)
|
||||
{
|
||||
list = (DWORD *)
|
||||
HeapAlloc (GetProcessHeap (), 0, num_req * sizeof (DWORD));
|
||||
num = num_req;
|
||||
num_req = GetConsoleProcessList (list, num);
|
||||
if (num_req > num)
|
||||
HeapFree (GetProcessHeap (), 0, list);
|
||||
else
|
||||
break;
|
||||
}
|
||||
num = num_req;
|
||||
|
||||
tmp = 0;
|
||||
for (int i=0; i<num; i++)
|
||||
for (DWORD i=0; i<num; i++)
|
||||
if ((match && list[i] == pid) || (!match && list[i] != pid))
|
||||
{
|
||||
tmp = list[i];
|
||||
//break;
|
||||
break;
|
||||
}
|
||||
HeapFree (GetProcessHeap (), 0, list);
|
||||
return tmp;
|
||||
|
|
|
@ -71,7 +71,7 @@ struct pipe_reply {
|
|||
DWORD error;
|
||||
};
|
||||
|
||||
static bool pcon_attached[NTTYS];
|
||||
static int pcon_attached_to = -1;
|
||||
static bool isHybrid;
|
||||
|
||||
#if USE_API_HOOK
|
||||
|
@ -85,7 +85,6 @@ set_switch_to_pcon (void)
|
|||
fhandler_base *fh = cfd;
|
||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||
ptys->set_switch_to_pcon ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,25 +338,6 @@ fhandler_pty_common::__release_output_mutex (const char *fn, int ln)
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool switch_to_pcon_prev;
|
||||
|
||||
bool
|
||||
fhandler_pty_common::check_switch_to_pcon (void)
|
||||
{
|
||||
bool switch_to_pcon_now = get_ttyp ()->switch_to_pcon;
|
||||
if (!isHybrid && !switch_to_pcon_prev && switch_to_pcon_now)
|
||||
{
|
||||
Sleep (40);
|
||||
/* Check again */
|
||||
switch_to_pcon_now = get_ttyp ()->switch_to_pcon;
|
||||
if (switch_to_pcon_now)
|
||||
switch_to_pcon_prev = true;
|
||||
}
|
||||
else
|
||||
switch_to_pcon_prev = switch_to_pcon_now;
|
||||
return switch_to_pcon_prev;
|
||||
}
|
||||
|
||||
/* Process pty input. */
|
||||
|
||||
void
|
||||
|
@ -553,7 +533,7 @@ out:
|
|||
|
||||
fhandler_pty_slave::fhandler_pty_slave (int unit)
|
||||
: fhandler_pty_common (), inuse (NULL), output_handle_cyg (NULL),
|
||||
io_handle_cyg (NULL)
|
||||
io_handle_cyg (NULL), pid_restore (0)
|
||||
{
|
||||
if (unit >= 0)
|
||||
dev ().parse (DEV_PTYS_MAJOR, unit);
|
||||
|
@ -562,32 +542,33 @@ fhandler_pty_slave::fhandler_pty_slave (int unit)
|
|||
fhandler_pty_slave::~fhandler_pty_slave ()
|
||||
{
|
||||
if (!get_ttyp ())
|
||||
{
|
||||
/* Why it comes here? */
|
||||
init_console_handler (false);
|
||||
FreeConsole ();
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
else if (getPseudoConsole ())
|
||||
/* Why comes here? Who clears _tc? */
|
||||
return;
|
||||
if (getPseudoConsole ())
|
||||
{
|
||||
int used = 0;
|
||||
int attached = 0;
|
||||
cygheap_fdenum cfd (false);
|
||||
while (cfd.next () >= 0)
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR &&
|
||||
cfd->get_minor () == get_minor ())
|
||||
used ++;
|
||||
{
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR ||
|
||||
cfd->get_major () == DEV_CONS_MAJOR)
|
||||
used ++;
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR &&
|
||||
cfd->get_minor () == pcon_attached_to)
|
||||
attached ++;
|
||||
}
|
||||
|
||||
/* Call FreeConsole() if no pty slave on this pty is
|
||||
opened and the process is attached to the pseudo
|
||||
console corresponding to this pty. This is needed
|
||||
to make GNU screen and tmux work in Windows 10 1903. */
|
||||
if (used == 0 &&
|
||||
fhandler_console::get_console_process_id (getHelperProcessId (),
|
||||
true))
|
||||
/* Call FreeConsole() if no tty is opened and the process
|
||||
is attached to console corresponding to tty. This is
|
||||
needed to make GNU screen and tmux work in Windows 10
|
||||
1903. */
|
||||
if (attached == 0)
|
||||
pcon_attached_to = -1;
|
||||
if (used == 0)
|
||||
{
|
||||
init_console_handler (false);
|
||||
FreeConsole ();
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -771,7 +752,27 @@ fhandler_pty_slave::open (int flags, mode_t)
|
|||
set_output_handle (to_master_local);
|
||||
set_output_handle_cyg (to_master_cyg_local);
|
||||
|
||||
fhandler_console::need_invisible ();
|
||||
if (!getPseudoConsole ())
|
||||
{
|
||||
fhandler_console::need_invisible ();
|
||||
pcon_attached_to = -1;
|
||||
}
|
||||
else if (!fhandler_console::get_console_process_id
|
||||
(GetCurrentProcessId (), true))
|
||||
{
|
||||
fhandler_console::need_invisible ();
|
||||
pcon_attached_to = -1;
|
||||
}
|
||||
else if (fhandler_console::get_console_process_id
|
||||
(getHelperProcessId (), true))
|
||||
/* Attached to pcon of this pty */
|
||||
{
|
||||
pcon_attached_to = get_minor ();
|
||||
init_console_handler (true);
|
||||
}
|
||||
else if (pcon_attached_to < 0)
|
||||
fhandler_console::need_invisible ();
|
||||
|
||||
set_open_status ();
|
||||
return 1;
|
||||
|
||||
|
@ -824,12 +825,13 @@ fhandler_pty_slave::close ()
|
|||
if (!ForceCloseHandle (get_handle_cyg ()))
|
||||
termios_printf ("CloseHandle (get_handle_cyg ()<%p>), %E",
|
||||
get_handle_cyg ());
|
||||
if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ()))
|
||||
if (!getPseudoConsole () &&
|
||||
(unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ()))
|
||||
fhandler_console::free_console (); /* assumes that we are the last pty closer */
|
||||
fhandler_pty_common::close ();
|
||||
if (!ForceCloseHandle (output_mutex))
|
||||
termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
|
||||
if (pcon_attached[get_minor ()])
|
||||
if (pcon_attached_to == get_minor ())
|
||||
get_ttyp ()->num_pcon_attached_slaves --;
|
||||
return 0;
|
||||
}
|
||||
|
@ -874,14 +876,53 @@ fhandler_pty_slave::init (HANDLE h, DWORD a, mode_t)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_pty_slave::try_reattach_pcon (void)
|
||||
{
|
||||
pid_restore = 0;
|
||||
|
||||
/* Do not detach from the console because re-attaching will
|
||||
fail if helper process is running as service account. */
|
||||
if (pcon_attached_to >= 0 &&
|
||||
cygwin_shared->tty[pcon_attached_to]->attach_pcon_in_fork)
|
||||
return false;
|
||||
|
||||
pid_restore =
|
||||
fhandler_console::get_console_process_id (GetCurrentProcessId (),
|
||||
false);
|
||||
/* If pid_restore is not set, give up. */
|
||||
if (!pid_restore)
|
||||
return false;
|
||||
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (getHelperProcessId ()))
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(helper=%d) failed. 0x%08lx",
|
||||
get_minor (), getHelperProcessId (), GetLastError ());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_pty_slave::restore_reattach_pcon (void)
|
||||
{
|
||||
if (pid_restore)
|
||||
{
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (pid_restore))
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(restore=%d) failed. 0x%08lx",
|
||||
get_minor (), pid_restore, GetLastError ());
|
||||
pcon_attached_to = -1;
|
||||
}
|
||||
}
|
||||
pid_restore = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_pty_slave::set_switch_to_pcon (void)
|
||||
{
|
||||
if (!pcon_attached[get_minor ()])
|
||||
{
|
||||
isHybrid = false;
|
||||
return;
|
||||
}
|
||||
if (!isHybrid)
|
||||
{
|
||||
reset_switch_to_pcon ();
|
||||
|
@ -889,6 +930,16 @@ fhandler_pty_slave::set_switch_to_pcon (void)
|
|||
}
|
||||
if (!get_ttyp ()->switch_to_pcon)
|
||||
{
|
||||
pid_restore = 0;
|
||||
if (pcon_attached_to != get_minor ())
|
||||
if (!try_reattach_pcon ())
|
||||
goto skip_console_setting;
|
||||
FlushConsoleInputBuffer (get_handle ());
|
||||
DWORD mode;
|
||||
GetConsoleMode (get_handle (), &mode);
|
||||
SetConsoleMode (get_handle (), mode | ENABLE_ECHO_INPUT);
|
||||
skip_console_setting:
|
||||
restore_reattach_pcon ();
|
||||
Sleep (20);
|
||||
if (get_ttyp ()->pcon_pid == 0 ||
|
||||
kill (get_ttyp ()->pcon_pid, 0) != 0)
|
||||
|
@ -904,7 +955,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
|
|||
return;
|
||||
if (isHybrid)
|
||||
{
|
||||
set_switch_to_pcon ();
|
||||
this->set_switch_to_pcon ();
|
||||
return;
|
||||
}
|
||||
if (get_ttyp ()->pcon_pid &&
|
||||
|
@ -918,7 +969,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
|
|||
DWORD mode;
|
||||
GetConsoleMode (get_handle (), &mode);
|
||||
SetConsoleMode (get_handle (), mode & ~ENABLE_ECHO_INPUT);
|
||||
Sleep (60); /* Wait for pty_master_fwd_thread() */
|
||||
Sleep (20); /* Wait for pty_master_fwd_thread() */
|
||||
}
|
||||
get_ttyp ()->pcon_pid = 0;
|
||||
get_ttyp ()->switch_to_pcon = false;
|
||||
|
@ -927,43 +978,31 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
|
|||
void
|
||||
fhandler_pty_slave::push_to_pcon_screenbuffer (const char *ptr, size_t len)
|
||||
{
|
||||
DWORD pidRestore = 0;
|
||||
if (!fhandler_console::get_console_process_id (getHelperProcessId (), true))
|
||||
if (pcon_attached[get_minor ()])
|
||||
{
|
||||
Sleep (20);
|
||||
/* Check again */
|
||||
if (!fhandler_console::get_console_process_id
|
||||
(getHelperProcessId (), true))
|
||||
{
|
||||
system_printf ("pty%d: pcon_attach mismatch?????? (%p)",
|
||||
get_minor (), this);
|
||||
//pcon_attached[get_minor ()] = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* If not attached pseudo console yet, try to attach temporally. */
|
||||
if (!pcon_attached[get_minor ()])
|
||||
bool attached =
|
||||
!!fhandler_console::get_console_process_id (getHelperProcessId (), true);
|
||||
if (!attached && pcon_attached_to == get_minor ())
|
||||
{
|
||||
if (has_master_opened ())
|
||||
return;
|
||||
|
||||
pidRestore =
|
||||
fhandler_console::get_console_process_id (GetCurrentProcessId (),
|
||||
false);
|
||||
/* If pidRestore is not set, give up to push. */
|
||||
if (!pidRestore)
|
||||
return;
|
||||
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (getHelperProcessId ()))
|
||||
for (DWORD t0 = GetTickCount (); GetTickCount () - t0 < 100; )
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(%d) failed. (%p) %08lx",
|
||||
get_minor (), getHelperProcessId (),
|
||||
this, GetLastError ());
|
||||
goto detach;
|
||||
Sleep (1);
|
||||
attached = fhandler_console::get_console_process_id
|
||||
(getHelperProcessId (), true);
|
||||
if (attached)
|
||||
break;
|
||||
}
|
||||
if (!attached)
|
||||
{
|
||||
system_printf ("pty%d: pcon_attach_to mismatch??????", get_minor ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not attached to this pseudo console, try to attach temporarily. */
|
||||
pid_restore = 0;
|
||||
if (pcon_attached_to != get_minor ())
|
||||
if (!try_reattach_pcon ())
|
||||
goto detach;
|
||||
|
||||
char *buf;
|
||||
size_t nlen;
|
||||
DWORD origCP;
|
||||
|
@ -1005,7 +1044,7 @@ fhandler_pty_slave::push_to_pcon_screenbuffer (const char *ptr, size_t len)
|
|||
}
|
||||
if (!nlen) /* Nothing to be synchronized */
|
||||
goto cleanup;
|
||||
if (check_switch_to_pcon ())
|
||||
if (get_ttyp ()->switch_to_pcon)
|
||||
goto cleanup;
|
||||
/* Remove ESC sequence which returns results to console
|
||||
input buffer. Without this, cursor position report
|
||||
|
@ -1060,27 +1099,7 @@ cleanup:
|
|||
SetConsoleOutputCP (origCP);
|
||||
HeapFree (GetProcessHeap (), 0, buf);
|
||||
detach:
|
||||
if (!pcon_attached[get_minor ()])
|
||||
{
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (pidRestore))
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(%d) failed. (%p) %08lx",
|
||||
get_minor (), pidRestore, this, GetLastError ());
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_pty_slave::has_master_opened (void)
|
||||
{
|
||||
cygheap_fdenum cfd (false);
|
||||
while (cfd.next () >= 0)
|
||||
if (cfd->get_major () == DEV_PTYM_MAJOR &&
|
||||
cfd->get_minor () == get_minor ())
|
||||
return true;
|
||||
return false;
|
||||
restore_reattach_pcon ();
|
||||
}
|
||||
|
||||
ssize_t __stdcall
|
||||
|
@ -1100,7 +1119,7 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
|
|||
|
||||
char *buf;
|
||||
ssize_t nlen;
|
||||
UINT targetCodePage = (check_switch_to_pcon ()) ?
|
||||
UINT targetCodePage = get_ttyp ()->switch_to_pcon ?
|
||||
GetConsoleOutputCP () : get_ttyp ()->TermCodePage;
|
||||
if (targetCodePage != get_ttyp ()->TermCodePage)
|
||||
{
|
||||
|
@ -1127,18 +1146,25 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
|
|||
nlen = len;
|
||||
}
|
||||
|
||||
/* If not attached to this pseudo console, try to attach temporarily. */
|
||||
pid_restore = 0;
|
||||
bool fallback = false;
|
||||
if (get_ttyp ()->switch_to_pcon && pcon_attached_to != get_minor ())
|
||||
if (!try_reattach_pcon ())
|
||||
fallback = true;
|
||||
|
||||
DWORD dwMode, flags;
|
||||
flags = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (!(get_ttyp ()->ti.c_oflag & OPOST) ||
|
||||
!(get_ttyp ()->ti.c_oflag & ONLCR))
|
||||
flags |= DISABLE_NEWLINE_AUTO_RETURN;
|
||||
if (check_switch_to_pcon ())
|
||||
if (get_ttyp ()->switch_to_pcon && !fallback)
|
||||
{
|
||||
GetConsoleMode (get_output_handle (), &dwMode);
|
||||
SetConsoleMode (get_output_handle (), dwMode | flags);
|
||||
}
|
||||
HANDLE to =
|
||||
check_switch_to_pcon () ? get_output_handle () : get_output_handle_cyg ();
|
||||
HANDLE to = (get_ttyp ()->switch_to_pcon && !fallback) ?
|
||||
get_output_handle () : get_output_handle_cyg ();
|
||||
acquire_output_mutex (INFINITE);
|
||||
if (!process_opost_output (to, buf, nlen, false))
|
||||
{
|
||||
|
@ -1157,8 +1183,10 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
|
|||
release_output_mutex ();
|
||||
HeapFree (GetProcessHeap (), 0, buf);
|
||||
flags = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (check_switch_to_pcon ())
|
||||
SetConsoleMode (get_output_handle (), dwMode | flags);
|
||||
if (get_ttyp ()->switch_to_pcon && !fallback)
|
||||
SetConsoleMode (get_output_handle (), dwMode);
|
||||
|
||||
restore_reattach_pcon ();
|
||||
|
||||
/* Push slave output to pseudo console screen buffer */
|
||||
if (getPseudoConsole ())
|
||||
|
@ -1299,9 +1327,15 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
|
|||
}
|
||||
goto out;
|
||||
}
|
||||
if (check_switch_to_pcon () &&
|
||||
!get_ttyp ()->mask_switch_to_pcon)
|
||||
if (get_ttyp ()->switch_to_pcon &&
|
||||
(!get_ttyp ()->mask_switch_to_pcon || ALWAYS_USE_PCON))
|
||||
{
|
||||
if (!try_reattach_pcon ())
|
||||
{
|
||||
restore_reattach_pcon ();
|
||||
goto do_read_cyg;
|
||||
}
|
||||
|
||||
DWORD dwMode;
|
||||
GetConsoleMode (get_handle (), &dwMode);
|
||||
DWORD flags = ENABLE_VIRTUAL_TERMINAL_INPUT;
|
||||
|
@ -1344,8 +1378,13 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
|
|||
ResetEvent (input_available_event);
|
||||
ReleaseMutex (input_mutex);
|
||||
len = rlen;
|
||||
|
||||
restore_reattach_pcon ();
|
||||
mask_switch_to_pcon (false);
|
||||
return;
|
||||
}
|
||||
|
||||
do_read_cyg:
|
||||
if (!bytes_available (bytes_in_pipe))
|
||||
{
|
||||
ReleaseMutex (input_mutex);
|
||||
|
@ -1611,31 +1650,13 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
|
|||
case TIOCSWINSZ:
|
||||
if (getPseudoConsole ())
|
||||
{
|
||||
/* If not attached pseudo console yet, try to attach
|
||||
temporally. */
|
||||
DWORD pidRestore = 0;
|
||||
if (!pcon_attached[get_minor ()])
|
||||
{
|
||||
if (has_master_opened () && get_ttyp ()->attach_pcon_in_fork)
|
||||
goto resize_cyg;
|
||||
/* If not attached to this pseudo console,
|
||||
try to attach temporarily. */
|
||||
pid_restore = 0;
|
||||
if (pcon_attached_to != get_minor ())
|
||||
if (!try_reattach_pcon ())
|
||||
goto cleanup;
|
||||
|
||||
pidRestore = fhandler_console::get_console_process_id
|
||||
(GetCurrentProcessId (), false);
|
||||
|
||||
/* This happens at mintty startup if fhandler_console::
|
||||
need_invisible() is called in stdio_init() in dtable.cc */
|
||||
if (!pidRestore) /* Give up to resize pseudo console */
|
||||
goto resize_cyg;
|
||||
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (getHelperProcessId ()))
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(%d) failed. (%p) %08lx",
|
||||
get_minor(), getHelperProcessId (),
|
||||
this, GetLastError ());
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
COORD size;
|
||||
size.X = ((struct winsize *) arg)->ws_col;
|
||||
size.Y = ((struct winsize *) arg)->ws_row;
|
||||
|
@ -1653,20 +1674,9 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
|
|||
rect.Bottom = size.Y-1;
|
||||
SetConsoleWindowInfo (get_output_handle (), TRUE, &rect);
|
||||
cleanup:
|
||||
/* Detach from pseudo console and resume. */
|
||||
if (pidRestore)
|
||||
{
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (pidRestore))
|
||||
{
|
||||
system_printf ("pty%d: AttachConsole(%d) failed. (%p) %08lx",
|
||||
get_minor (), pidRestore,
|
||||
this, GetLastError ());
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
}
|
||||
restore_reattach_pcon ();
|
||||
}
|
||||
resize_cyg:
|
||||
|
||||
if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
|
||||
|| get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
|
||||
{
|
||||
|
@ -2042,7 +2052,6 @@ fhandler_pty_master::close ()
|
|||
ClosePseudoConsole = (VOID (WINAPI *) (HPCON)) func;
|
||||
ClosePseudoConsole (getPseudoConsole ());
|
||||
}
|
||||
get_ttyp ()->hPseudoConsole = NULL;
|
||||
get_ttyp ()->switch_to_pcon = false;
|
||||
}
|
||||
if (get_ttyp ()->getsid () > 0)
|
||||
|
@ -2096,8 +2105,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
|
|||
|
||||
/* Write terminal input to to_slave pipe instead of output_handle
|
||||
if current application is native console application. */
|
||||
if (check_switch_to_pcon () &&
|
||||
!get_ttyp ()->mask_switch_to_pcon)
|
||||
if (get_ttyp ()->switch_to_pcon &&
|
||||
(!get_ttyp ()->mask_switch_to_pcon || ALWAYS_USE_PCON))
|
||||
{
|
||||
char *buf;
|
||||
size_t nlen;
|
||||
|
@ -2702,8 +2711,9 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe)
|
|||
if (fhandler_console::get_console_process_id (getHelperProcessId (),
|
||||
true))
|
||||
{
|
||||
if (!pcon_attached[get_minor ()])
|
||||
if (pcon_attached_to != get_minor ())
|
||||
{
|
||||
pcon_attached_to = get_minor ();
|
||||
init_console_handler (true);
|
||||
#if USE_OWN_NLS_FUNC
|
||||
char locale[ENCODING_LEN + 1] = "C";
|
||||
|
@ -2786,19 +2796,20 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe)
|
|||
WriteFile (get_output_handle_cyg (),
|
||||
"\033[H\033[J", 6, &n, NULL);
|
||||
|
||||
pcon_attached[get_minor ()] = true;
|
||||
get_ttyp ()->num_pcon_attached_slaves ++;
|
||||
}
|
||||
}
|
||||
else
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
if (pcon_attached[get_minor ()] && native_maybe)
|
||||
if (pcon_attached_to == get_minor () && (native_maybe || ALWAYS_USE_PCON))
|
||||
{
|
||||
FlushConsoleInputBuffer (get_handle ());
|
||||
DWORD mode;
|
||||
GetConsoleMode (get_handle (), &mode);
|
||||
SetConsoleMode (get_handle (), mode | ENABLE_ECHO_INPUT);
|
||||
SetConsoleMode (get_handle (),
|
||||
(mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT) |
|
||||
ENABLE_ECHO_INPUT |
|
||||
ENABLE_LINE_INPUT |
|
||||
ENABLE_PROCESSED_INPUT);
|
||||
Sleep (20);
|
||||
if (get_ttyp ()->pcon_pid == 0 ||
|
||||
kill (get_ttyp ()->pcon_pid, 0) != 0)
|
||||
|
@ -2826,23 +2837,28 @@ fhandler_pty_slave::fixup_after_exec ()
|
|||
else if (getPseudoConsole ())
|
||||
{
|
||||
int used = 0;
|
||||
int attached = 0;
|
||||
cygheap_fdenum cfd (false);
|
||||
while (cfd.next () >= 0)
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR &&
|
||||
cfd->get_minor () == get_minor ())
|
||||
used ++;
|
||||
{
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR ||
|
||||
cfd->get_major () == DEV_CONS_MAJOR)
|
||||
used ++;
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR &&
|
||||
cfd->get_minor () == pcon_attached_to)
|
||||
attached ++;
|
||||
}
|
||||
|
||||
/* Call FreeConsole() if no pty slave on this pty is
|
||||
opened and the process is attached to the pseudo
|
||||
console corresponding to this pty. This is needed
|
||||
to make GNU screen and tmux work in Windows 10 1903. */
|
||||
if (used == 1 /* About to close this one */ &&
|
||||
fhandler_console::get_console_process_id (getHelperProcessId (),
|
||||
true))
|
||||
/* Call FreeConsole() if no tty is opened and the process
|
||||
is attached to console corresponding to tty. This is
|
||||
needed to make GNU screen and tmux work in Windows 10
|
||||
1903. */
|
||||
if (attached == 1 && get_minor () == pcon_attached_to)
|
||||
pcon_attached_to = -1;
|
||||
if (used == 1 /* About to close this tty */)
|
||||
{
|
||||
init_console_handler (false);
|
||||
FreeConsole ();
|
||||
pcon_attached[get_minor ()] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3049,7 +3065,7 @@ fhandler_pty_master::pty_master_fwd_thread ()
|
|||
{
|
||||
/* Avoid duplicating slave output which is already sent to
|
||||
to_master_cyg */
|
||||
if (!check_switch_to_pcon ())
|
||||
if (!get_ttyp ()->switch_to_pcon)
|
||||
continue;
|
||||
|
||||
/* Avoid setting window title to "cygwin-console-helper.exe" */
|
||||
|
@ -3064,25 +3080,42 @@ fhandler_pty_master::pty_master_fwd_thread ()
|
|||
}
|
||||
else if ((state == 1 && outbuf[i] == ']') ||
|
||||
(state == 2 && outbuf[i] == '0') ||
|
||||
(state == 3 && outbuf[i] == ';') ||
|
||||
(state == 4 && outbuf[i] == '\0'))
|
||||
(state == 3 && outbuf[i] == ';'))
|
||||
{
|
||||
state ++;
|
||||
continue;
|
||||
}
|
||||
else if (state == 5 && outbuf[i] == '\a')
|
||||
else if (state == 4 && outbuf[i] == '\a')
|
||||
{
|
||||
memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
|
||||
state = 0;
|
||||
rlen = wlen = start_at + rlen - i - 1;
|
||||
continue;
|
||||
}
|
||||
else if (state != 4 || outbuf[i] == '\a')
|
||||
else if (outbuf[i] == '\a')
|
||||
{
|
||||
state = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove ESC sequence which returns results to console
|
||||
input buffer. Without this, cursor position report
|
||||
is put into the input buffer as a garbage. */
|
||||
/* Remove ESC sequence to report cursor position. */
|
||||
char *p0;
|
||||
while ((p0 = (char *) memmem (outbuf, rlen, "\033[6n", 4)))
|
||||
{
|
||||
memmove (p0, p0+4, rlen - (p0+4 - outbuf));
|
||||
rlen -= 4;
|
||||
}
|
||||
/* Remove ESC sequence to report terminal identity. */
|
||||
while ((p0 = (char *) memmem (outbuf, rlen, "\033[0c", 4)))
|
||||
{
|
||||
memmove (p0, p0+4, rlen - (p0+4 - outbuf));
|
||||
rlen -= 4;
|
||||
}
|
||||
wlen = rlen;
|
||||
|
||||
char *buf;
|
||||
size_t nlen;
|
||||
if (get_ttyp ()->TermCodePage != CP_UTF8)
|
||||
|
|
|
@ -140,20 +140,24 @@ frok::child (volatile char * volatile here)
|
|||
{
|
||||
fhandler_base *fh = cfd;
|
||||
fhandler_pty_master *ptym = (fhandler_pty_master *) fh;
|
||||
if (ptym->getPseudoConsole () &&
|
||||
!fhandler_console::get_console_process_id (
|
||||
ptym->getHelperProcessId (), true))
|
||||
|
||||
if (ptym->getPseudoConsole ())
|
||||
{
|
||||
debug_printf ("found a PTY master %d: helper_PID=%d",
|
||||
ptym->get_minor (), ptym->getHelperProcessId ());
|
||||
if (ptym->attach_pcon_in_fork ())
|
||||
if (fhandler_console::get_console_process_id (
|
||||
ptym->getHelperProcessId (), true))
|
||||
/* Already attached */
|
||||
break;
|
||||
else
|
||||
{
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (ptym->getHelperProcessId ()))
|
||||
/* Error */;
|
||||
else
|
||||
break;
|
||||
if (ptym->attach_pcon_in_fork ())
|
||||
{
|
||||
FreeConsole ();
|
||||
if (!AttachConsole (ptym->getHelperProcessId ()))
|
||||
/* Error */;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue