Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2019-09-04 04:45:35 +0300
committerCorinna Vinschen <corinna@vinschen.de>2019-09-04 13:05:15 +0300
commit583102e7c9255ae25310154995f855e4f573f81c (patch)
tree14540c4e757ad37359ccabfae947c2e670071f95
parentffbb9b49711f6a8e3c4f83b226ff9476327dcb61 (diff)
Cygwin: pty: Fix state management for pseudo console support.
- Pseudo console support introduced by commit 169d65a5774acc76ce3f3feeedcbae7405aa9b57 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.
-rw-r--r--winsup/cygwin/dtable.cc38
-rw-r--r--winsup/cygwin/fhandler.h6
-rw-r--r--winsup/cygwin/fhandler_console.cc25
-rw-r--r--winsup/cygwin/fhandler_tty.cc385
-rw-r--r--winsup/cygwin/fork.cc24
-rw-r--r--winsup/cygwin/spawn.cc65
6 files changed, 289 insertions, 254 deletions
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index ba5d16206..4e9b6ed56 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -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);
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index c75e40c0a..e8c165100 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -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;
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index 997c50d23..1b034f4b9 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index f76f7b262..262c41bfe 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -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 ++;
-
- /* 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))
+ {
+ 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 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::set_switch_to_pcon (void)
+fhandler_pty_slave::restore_reattach_pcon (void)
{
- if (!pcon_attached[get_minor ()])
+ if (pid_restore)
{
- isHybrid = false;
- return;
+ 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 (!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; )
+ {
+ Sleep (1);
+ attached = fhandler_console::get_console_process_id
+ (getHelperProcessId (), true);
+ if (attached)
+ break;
+ }
+ if (!attached)
{
- system_printf ("pty%d: AttachConsole(%d) failed. (%p) %08lx",
- get_minor (), getHelperProcessId (),
- this, GetLastError ());
- goto detach;
+ 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;
-
- 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;
+ /* 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;
- 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 ++;
-
- /* 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))
+ {
+ 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 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)
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 0c089dbe9..a3a7e7505 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -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;
+ }
}
}
}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 98612bd0f..4bb28c47b 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -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)
+ /* Already attached */
+ attach_to_pcon = true;
+ break;
+ }
+ else
+ {
+ FreeConsole ();
+ if (AttachConsole (dwHelperProcessId))
{
- ptys->set_handle (ptys->get_handle_cyg ());
- SetStdHandle (target[fd],
- ptys->get_handle ());
+ attach_to_pcon = true;
+ break;
}
else
{
- ptys->set_output_handle (
- ptys->get_output_handle_cyg ());
- SetStdHandle (target[fd],
- ptys->get_output_handle ());
+ /* 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 ());
+ }
}
}
- else
- {
- init_console_handler (true);
- attach_to_pcon = true;
- break;
- }
}
}
}
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