mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-08 18:19:08 +08:00
Cygwin: pty: Make apps using console APIs be able to debug with gdb.
- After commit bb428520, there has been the disadvantage: 2) The apps which use console API cannot be debugged with gdb. This is because pseudo console is not activated since gdb uses CreateProcess() rather than exec(). Even with this limitation, attaching gdb to native app, in which pseudo console is already activated, works. This patch clears this disadvantage.
This commit is contained in:
parent
9f783a84f5
commit
7c41c4a77b
@ -2475,6 +2475,8 @@ 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;
|
||||
HANDLE slave_reading;
|
||||
LONG num_reader;
|
||||
|
||||
/* Helper functions for fchmod and fchown. */
|
||||
bool fch_open_handles (bool chown);
|
||||
@ -2552,6 +2554,7 @@ class fhandler_pty_slave: public fhandler_pty_common
|
||||
static void transfer_input (xfer_dir dir, HANDLE from, tty *ttyp,
|
||||
_minor_t unit, HANDLE input_available_event);
|
||||
HANDLE get_input_available_event (void) { return input_available_event; }
|
||||
bool pcon_activated (void) { return get_ttyp ()->h_pseudo_console; }
|
||||
};
|
||||
|
||||
#define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
|
||||
|
@ -27,6 +27,7 @@ details. */
|
||||
#include "cygwait.h"
|
||||
#include "registry.h"
|
||||
#include "tls_pbuf.h"
|
||||
#include "winf.h"
|
||||
|
||||
#ifndef PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
|
||||
#define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016
|
||||
@ -87,21 +88,47 @@ get_console_process_id (DWORD pid, bool match)
|
||||
}
|
||||
|
||||
static bool isHybrid;
|
||||
static HANDLE h_gdb_process;
|
||||
|
||||
static void
|
||||
set_switch_to_pcon (HANDLE h)
|
||||
set_switch_to_pcon (HANDLE *in, HANDLE *out, HANDLE *err, bool iscygwin)
|
||||
{
|
||||
cygheap_fdenum cfd (false);
|
||||
int fd;
|
||||
fhandler_base *replace_in = NULL, *replace_out = NULL, *replace_err = NULL;
|
||||
fhandler_pty_slave *ptys_pcon = NULL;
|
||||
while ((fd = cfd.next ()) >= 0)
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR)
|
||||
{
|
||||
fhandler_base *fh = cfd;
|
||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||
if (h == ptys->get_handle ())
|
||||
ptys->set_switch_to_pcon ();
|
||||
return;
|
||||
}
|
||||
{
|
||||
if (*in == cfd->get_handle () ||
|
||||
(fd == 0 && *in == GetStdHandle (STD_INPUT_HANDLE)))
|
||||
replace_in = (fhandler_base *) cfd;
|
||||
if (*out == cfd->get_output_handle () ||
|
||||
(fd == 1 && *out == GetStdHandle (STD_OUTPUT_HANDLE)))
|
||||
replace_out = (fhandler_base *) cfd;
|
||||
if (*err == cfd->get_output_handle () ||
|
||||
(fd == 2 && *err == GetStdHandle (STD_ERROR_HANDLE)))
|
||||
replace_err = (fhandler_base *) cfd;
|
||||
if (cfd->get_major () == DEV_PTYS_MAJOR)
|
||||
{
|
||||
fhandler_base *fh = cfd;
|
||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||
if (*in == ptys->get_handle ())
|
||||
ptys_pcon = ptys;
|
||||
}
|
||||
}
|
||||
if (!iscygwin && ptys_pcon)
|
||||
ptys_pcon->set_switch_to_pcon ();
|
||||
if (replace_in)
|
||||
{
|
||||
if (iscygwin && ptys_pcon->pcon_activated ())
|
||||
*in = replace_in->get_handle_cyg ();
|
||||
else
|
||||
*in = replace_in->get_handle ();
|
||||
}
|
||||
if (replace_out)
|
||||
*out = replace_out->get_output_handle ();
|
||||
if (replace_err)
|
||||
*err = replace_err->get_output_handle ();
|
||||
}
|
||||
|
||||
#define DEF_HOOK(name) static __typeof__ (name) *name##_Orig
|
||||
@ -115,16 +142,55 @@ CreateProcessA_Hooked
|
||||
BOOL inh, DWORD f, LPVOID e, LPCSTR d,
|
||||
LPSTARTUPINFOA si, LPPROCESS_INFORMATION pi)
|
||||
{
|
||||
HANDLE h;
|
||||
if (!isHybrid)
|
||||
STARTUPINFOEXA siex = {0, };
|
||||
if (si->cb == sizeof (STARTUPINFOEXA))
|
||||
siex = *(STARTUPINFOEXA *)si;
|
||||
else
|
||||
siex.StartupInfo = *si;
|
||||
STARTUPINFOA *siov = &siex.StartupInfo;
|
||||
if (!(si->dwFlags & STARTF_USESTDHANDLES))
|
||||
{
|
||||
if (si->dwFlags & STARTF_USESTDHANDLES)
|
||||
h = si->hStdInput;
|
||||
else
|
||||
h = GetStdHandle (STD_INPUT_HANDLE);
|
||||
set_switch_to_pcon (h);
|
||||
siov->dwFlags |= STARTF_USESTDHANDLES;
|
||||
siov->hStdInput = GetStdHandle (STD_INPUT_HANDLE);
|
||||
siov->hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
siov->hStdError = GetStdHandle (STD_ERROR_HANDLE);
|
||||
}
|
||||
return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
||||
path_conv path;
|
||||
tmp_pathbuf tp;
|
||||
char *prog =tp.c_get ();
|
||||
if (n)
|
||||
__small_sprintf (prog, "%s", n);
|
||||
else
|
||||
{
|
||||
__small_sprintf (prog, "%s", c);
|
||||
char *p = prog;
|
||||
char *p1;
|
||||
do
|
||||
if ((p1 = strstr (p, ".exe")) || (p1 = strstr (p, ".com")))
|
||||
{
|
||||
p = p1 + 4;
|
||||
if (*p == ' ')
|
||||
{
|
||||
*p = '\0';
|
||||
path.check (prog);
|
||||
*p = ' ';
|
||||
}
|
||||
else if (*p == '\0')
|
||||
path.check (prog);
|
||||
}
|
||||
while (!path.exists() && p1);
|
||||
}
|
||||
const char *argv[] = {"", NULL}; /* Dummy */
|
||||
av av1;
|
||||
av1.setup ("", path, "", 1, argv, false);
|
||||
set_switch_to_pcon (&siov->hStdInput, &siov->hStdOutput, &siov->hStdError,
|
||||
path.iscygexec ());
|
||||
BOOL ret = CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, siov, pi);
|
||||
h_gdb_process = pi->hProcess;
|
||||
DuplicateHandle (GetCurrentProcess (), h_gdb_process,
|
||||
GetCurrentProcess (), &h_gdb_process,
|
||||
0, 0, DUPLICATE_SAME_ACCESS);
|
||||
return ret;
|
||||
}
|
||||
static BOOL WINAPI
|
||||
CreateProcessW_Hooked
|
||||
@ -132,16 +198,55 @@ CreateProcessW_Hooked
|
||||
BOOL inh, DWORD f, LPVOID e, LPCWSTR d,
|
||||
LPSTARTUPINFOW si, LPPROCESS_INFORMATION pi)
|
||||
{
|
||||
HANDLE h;
|
||||
if (!isHybrid)
|
||||
STARTUPINFOEXW siex = {0, };
|
||||
if (si->cb == sizeof (STARTUPINFOEXW))
|
||||
siex = *(STARTUPINFOEXW *)si;
|
||||
else
|
||||
siex.StartupInfo = *si;
|
||||
STARTUPINFOW *siov = &siex.StartupInfo;
|
||||
if (!(si->dwFlags & STARTF_USESTDHANDLES))
|
||||
{
|
||||
if (si->dwFlags & STARTF_USESTDHANDLES)
|
||||
h = si->hStdInput;
|
||||
else
|
||||
h = GetStdHandle (STD_INPUT_HANDLE);
|
||||
set_switch_to_pcon (h);
|
||||
siov->dwFlags |= STARTF_USESTDHANDLES;
|
||||
siov->hStdInput = GetStdHandle (STD_INPUT_HANDLE);
|
||||
siov->hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
siov->hStdError = GetStdHandle (STD_ERROR_HANDLE);
|
||||
}
|
||||
return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
||||
path_conv path;
|
||||
tmp_pathbuf tp;
|
||||
char *prog =tp.c_get ();
|
||||
if (n)
|
||||
__small_sprintf (prog, "%W", n);
|
||||
else
|
||||
{
|
||||
__small_sprintf (prog, "%W", c);
|
||||
char *p = prog;
|
||||
char *p1;
|
||||
do
|
||||
if ((p1 = strstr (p, ".exe")) || (p1 = strstr (p, ".com")))
|
||||
{
|
||||
p = p1 + 4;
|
||||
if (*p == ' ')
|
||||
{
|
||||
*p = '\0';
|
||||
path.check (prog);
|
||||
*p = ' ';
|
||||
}
|
||||
else if (*p == '\0')
|
||||
path.check (prog);
|
||||
}
|
||||
while (!path.exists() && p1);
|
||||
}
|
||||
const char *argv[] = {"", NULL}; /* Dummy */
|
||||
av av1;
|
||||
av1.setup ("", path, "", 1, argv, false);
|
||||
set_switch_to_pcon (&siov->hStdInput, &siov->hStdOutput, &siov->hStdError,
|
||||
path.iscygexec ());
|
||||
BOOL ret = CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, siov, pi);
|
||||
h_gdb_process = pi->hProcess;
|
||||
DuplicateHandle (GetCurrentProcess (), h_gdb_process,
|
||||
GetCurrentProcess (), &h_gdb_process,
|
||||
0, 0, DUPLICATE_SAME_ACCESS);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -529,7 +634,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), slave_reading (NULL), num_reader (0)
|
||||
{
|
||||
if (unit >= 0)
|
||||
dev ().parse (DEV_PTYS_MAJOR, unit);
|
||||
@ -835,15 +940,100 @@ fhandler_pty_slave::set_switch_to_pcon (void)
|
||||
if (!get_ttyp ()->switch_to_pcon_in)
|
||||
{
|
||||
isHybrid = true;
|
||||
if (get_ttyp ()->pcon_pid == 0 || !pinfo (get_ttyp ()->pcon_pid))
|
||||
get_ttyp ()->pcon_pid = myself->pid;
|
||||
get_ttyp ()->switch_to_pcon_in = true;
|
||||
setup_locale ();
|
||||
bool nopcon = (disable_pcon || !term_has_pcon_cap (NULL));
|
||||
if (!setup_pseudoconsole (nopcon))
|
||||
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_nat,
|
||||
get_handle_cyg (),
|
||||
get_ttyp (), get_minor (),
|
||||
input_available_event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fhandler_pty_slave::reset_switch_to_pcon (void)
|
||||
{
|
||||
if (h_gdb_process)
|
||||
{
|
||||
if (WaitForSingleObject (h_gdb_process, 0) == WAIT_TIMEOUT)
|
||||
{
|
||||
if (isHybrid)
|
||||
get_ttyp ()->wait_pcon_fwd (false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CloseHandle (h_gdb_process);
|
||||
h_gdb_process = NULL;
|
||||
if (isHybrid && get_ttyp ()->pcon_pid == myself->pid)
|
||||
{
|
||||
if (get_ttyp ()->switch_to_pcon_in)
|
||||
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||
get_handle (),
|
||||
get_ttyp (), get_minor (),
|
||||
input_available_event);
|
||||
if (get_ttyp ()->master_is_running_as_service)
|
||||
/* If the master is running as service, re-attaching to
|
||||
the console of the parent process will fail.
|
||||
Therefore, never close pseudo console here. */
|
||||
return;
|
||||
bool need_restore_handles = !!get_ttyp ()->h_pseudo_console;
|
||||
close_pseudoconsole (get_ttyp ());
|
||||
if (need_restore_handles)
|
||||
{
|
||||
pinfo p (get_ttyp ()->master_pid);
|
||||
HANDLE pty_owner =
|
||||
OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
|
||||
bool fix_in, fix_out, fix_err;
|
||||
fix_in =
|
||||
GetStdHandle (STD_INPUT_HANDLE) == get_handle ();
|
||||
fix_out =
|
||||
GetStdHandle (STD_OUTPUT_HANDLE) == get_output_handle ();
|
||||
fix_err =
|
||||
GetStdHandle (STD_ERROR_HANDLE) == get_output_handle ();
|
||||
if (pty_owner)
|
||||
{
|
||||
CloseHandle (get_handle ());
|
||||
DuplicateHandle (pty_owner, get_ttyp ()->from_master (),
|
||||
GetCurrentProcess (), &get_handle (),
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
CloseHandle (get_output_handle ());
|
||||
DuplicateHandle (pty_owner, get_ttyp ()->to_master (),
|
||||
GetCurrentProcess (),
|
||||
&get_output_handle (),
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||
CloseHandle (pty_owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
char pipe[MAX_PATH];
|
||||
__small_sprintf (pipe,
|
||||
"\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
|
||||
&cygheap->installation_key, get_minor ());
|
||||
pipe_request req = { GetCurrentProcessId () };
|
||||
pipe_reply repl;
|
||||
DWORD len;
|
||||
if (!CallNamedPipe (pipe, &req, sizeof req,
|
||||
&repl, sizeof repl, &len, 500))
|
||||
return; /* What can we do? */
|
||||
CloseHandle (get_handle ());
|
||||
set_handle (repl.from_master);
|
||||
CloseHandle (get_output_handle ());
|
||||
set_output_handle (repl.to_master);
|
||||
}
|
||||
if (fix_in)
|
||||
SetStdHandle (STD_INPUT_HANDLE, get_handle ());
|
||||
if (fix_out)
|
||||
SetStdHandle (STD_OUTPUT_HANDLE, get_output_handle ());
|
||||
if (fix_err)
|
||||
SetStdHandle (STD_ERROR_HANDLE, get_output_handle ());
|
||||
}
|
||||
get_ttyp ()->pcon_pid = 0;
|
||||
get_ttyp ()->switch_to_pcon_in = false;
|
||||
}
|
||||
isHybrid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (get_ttyp ()->pcon_pid && get_ttyp ()->pcon_pid != myself->pid
|
||||
&& !!pinfo (get_ttyp ()->pcon_pid))
|
||||
/* There is a process which is grabbing pseudo console. */
|
||||
@ -899,10 +1089,23 @@ fhandler_pty_slave::write (const void *ptr, size_t len)
|
||||
void
|
||||
fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
|
||||
{
|
||||
char name[MAX_PATH];
|
||||
shared_name (name, TTY_SLAVE_READING, get_minor ());
|
||||
HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name);
|
||||
CloseHandle (masked);
|
||||
|
||||
if (mask)
|
||||
{
|
||||
if (InterlockedIncrement (&num_reader) == 1)
|
||||
slave_reading = CreateEvent (&sec_none_nih, TRUE, FALSE, name);
|
||||
}
|
||||
else if (InterlockedDecrement (&num_reader) == 0)
|
||||
CloseHandle (slave_reading);
|
||||
|
||||
if (get_ttyp ()->switch_to_pcon_in
|
||||
&& (get_ttyp ()->pcon_pid == myself->pid
|
||||
|| !get_ttyp ()->h_pseudo_console)
|
||||
&& get_ttyp ()->mask_switch_to_pcon_in != mask)
|
||||
&& !!masked != mask)
|
||||
{
|
||||
if (mask)
|
||||
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||
@ -915,14 +1118,19 @@ fhandler_pty_slave::mask_switch_to_pcon_in (bool mask)
|
||||
get_ttyp (), get_minor (),
|
||||
input_available_event);
|
||||
}
|
||||
get_ttyp ()->mask_switch_to_pcon_in = mask;
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_pty_master::to_be_read_from_pcon (void)
|
||||
{
|
||||
char name[MAX_PATH];
|
||||
shared_name (name, TTY_SLAVE_READING, get_minor ());
|
||||
HANDLE masked = OpenEvent (READ_CONTROL, FALSE, name);
|
||||
CloseHandle (masked);
|
||||
|
||||
return get_ttyp ()->pcon_start
|
||||
|| (get_ttyp ()->switch_to_pcon_in && !get_ttyp ()->mask_switch_to_pcon_in);
|
||||
|| (get_ttyp ()->switch_to_pcon_in && !masked);
|
||||
}
|
||||
|
||||
void __reg3
|
||||
@ -2609,6 +2817,13 @@ pty_master_fwd_thread (VOID *arg)
|
||||
return fhandler_pty_master::pty_master_fwd_thread (&p);
|
||||
}
|
||||
|
||||
inline static bool
|
||||
is_running_as_service (void)
|
||||
{
|
||||
return check_token_membership (well_known_service_sid)
|
||||
|| cygheap->user.saved_sid () == well_known_system_sid;
|
||||
}
|
||||
|
||||
bool
|
||||
fhandler_pty_master::setup ()
|
||||
{
|
||||
@ -2655,8 +2870,15 @@ fhandler_pty_master::setup ()
|
||||
}
|
||||
|
||||
__small_sprintf (pipename, "pty%d-to-slave", unit);
|
||||
/* FILE_FLAG_OVERLAPPED is specified here in order to prevent
|
||||
PeekNamedPipe() from blocking in transfer_input().
|
||||
Accordig to the official document, in order to access the handle
|
||||
opened with FILE_FLAG_OVERLAPPED, it is mandatory to pass the
|
||||
OVERLAPP structure, but in fact, it seems that the access will
|
||||
fallback to the blocking access if it is not specified. */
|
||||
res = fhandler_pipe::create (&sec_none, &from_master, &to_slave,
|
||||
fhandler_pty_common::pipesize, pipename, 0);
|
||||
fhandler_pty_common::pipesize, pipename,
|
||||
FILE_FLAG_OVERLAPPED);
|
||||
if (res)
|
||||
{
|
||||
errstr = "input pipe";
|
||||
@ -2747,6 +2969,8 @@ fhandler_pty_master::setup ()
|
||||
|
||||
dev ().parse (DEV_PTYM_MAJOR, unit);
|
||||
|
||||
t.master_is_running_as_service = is_running_as_service ();
|
||||
|
||||
termios_printf ("this %p, pty%d opened - from_pty <%p,%p>, to_pty %p",
|
||||
this, unit, from_slave, get_handle (),
|
||||
get_output_handle ());
|
||||
@ -3068,6 +3292,14 @@ fhandler_pty_slave::setup_pseudoconsole (bool nopcon)
|
||||
CloseHandle (pi.hProcess);
|
||||
|
||||
/* Set handle */
|
||||
if (GetStdHandle (STD_INPUT_HANDLE) == get_handle ())
|
||||
SetStdHandle (STD_INPUT_HANDLE, hpConIn);
|
||||
if (GetStdHandle (STD_OUTPUT_HANDLE) == get_output_handle ())
|
||||
SetStdHandle (STD_OUTPUT_HANDLE, hpConOut);
|
||||
if (GetStdHandle (STD_ERROR_HANDLE) == get_output_handle ())
|
||||
SetStdHandle (STD_ERROR_HANDLE, hpConOut);
|
||||
|
||||
/* Fixup handles */
|
||||
HANDLE orig_input_handle = get_handle ();
|
||||
HANDLE orig_output_handle = get_output_handle ();
|
||||
cygheap_fdenum cfd (false);
|
||||
@ -3137,7 +3369,6 @@ fhandler_pty_slave::close_pseudoconsole (tty *ttyp)
|
||||
{
|
||||
if (ttyp->h_pseudo_console)
|
||||
{
|
||||
ttyp->wait_pcon_fwd ();
|
||||
ttyp->previous_code_page = GetConsoleCP ();
|
||||
ttyp->previous_output_code_page = GetConsoleOutputCP ();
|
||||
FreeConsole ();
|
||||
|
@ -1411,12 +1411,11 @@ pty_slave_cleanup (select_record *me, select_stuff *stuff)
|
||||
{
|
||||
fhandler_base *fh = (fhandler_base *) me->fh;
|
||||
fhandler_pty_slave *ptys = (fhandler_pty_slave *) fh;
|
||||
if (me->read_selected)
|
||||
ptys->mask_switch_to_pcon_in (false);
|
||||
|
||||
select_pipe_info *pi = (select_pipe_info *) stuff->device_specific_ptys;
|
||||
if (!pi)
|
||||
return;
|
||||
if (me->read_selected && pi->start)
|
||||
ptys->mask_switch_to_pcon_in (false);
|
||||
if (pi->thread)
|
||||
{
|
||||
pi->stop_thread = true;
|
||||
|
@ -964,6 +964,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
||||
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||
if (ptys_ttyp)
|
||||
{
|
||||
ptys_ttyp->wait_pcon_fwd ();
|
||||
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||
ptys_from_master,
|
||||
ptys_ttyp, ptys_unit,
|
||||
@ -990,6 +991,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
|
||||
res = -1;
|
||||
if (ptys_ttyp)
|
||||
{
|
||||
ptys_ttyp->wait_pcon_fwd ();
|
||||
fhandler_pty_slave::transfer_input (fhandler_pty_slave::to_cyg,
|
||||
ptys_from_master,
|
||||
ptys_ttyp, ptys_unit,
|
||||
|
@ -237,7 +237,6 @@ tty::init ()
|
||||
column = 0;
|
||||
h_pseudo_console = NULL;
|
||||
switch_to_pcon_in = false;
|
||||
mask_switch_to_pcon_in = false;
|
||||
pcon_pid = 0;
|
||||
term_code_page = 0;
|
||||
pcon_last_time = 0;
|
||||
@ -248,6 +247,7 @@ tty::init ()
|
||||
invisible_console_pid = 0;
|
||||
previous_code_page = 0;
|
||||
previous_output_code_page = 0;
|
||||
master_is_running_as_service = false;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
@ -294,7 +294,7 @@ tty_min::ttyname ()
|
||||
}
|
||||
|
||||
void
|
||||
tty::wait_pcon_fwd (void)
|
||||
tty::wait_pcon_fwd (bool init)
|
||||
{
|
||||
/* The forwarding in pseudo console sometimes stops for
|
||||
16-32 msec even if it already has data to transfer.
|
||||
@ -304,7 +304,8 @@ tty::wait_pcon_fwd (void)
|
||||
thread when the last data is transfered. */
|
||||
const int sleep_in_pcon = 16;
|
||||
const int time_to_wait = sleep_in_pcon * 2 + 1/* margine */;
|
||||
pcon_last_time = GetTickCount ();
|
||||
if (init)
|
||||
pcon_last_time = GetTickCount ();
|
||||
while (GetTickCount () - pcon_last_time < time_to_wait)
|
||||
{
|
||||
int tw = time_to_wait - (GetTickCount () - pcon_last_time);
|
||||
|
@ -21,6 +21,7 @@ details. */
|
||||
#define OUTPUT_MUTEX "cygtty.output.mutex"
|
||||
#define INPUT_MUTEX "cygtty.input.mutex"
|
||||
#define TTY_SLAVE_ALIVE "cygtty.slave_alive"
|
||||
#define TTY_SLAVE_READING "cygtty.slave_reading"
|
||||
|
||||
#include <sys/termios.h>
|
||||
|
||||
@ -98,7 +99,6 @@ private:
|
||||
HPCON h_pseudo_console;
|
||||
bool pcon_start;
|
||||
bool switch_to_pcon_in;
|
||||
bool mask_switch_to_pcon_in;
|
||||
pid_t pcon_pid;
|
||||
UINT term_code_page;
|
||||
DWORD pcon_last_time;
|
||||
@ -109,6 +109,7 @@ private:
|
||||
pid_t invisible_console_pid;
|
||||
UINT previous_code_page;
|
||||
UINT previous_output_code_page;
|
||||
bool master_is_running_as_service;
|
||||
|
||||
public:
|
||||
HANDLE from_master () const { return _from_master; }
|
||||
@ -142,7 +143,7 @@ public:
|
||||
void set_master_ctl_closed () {master_pid = -1;}
|
||||
static void __stdcall create_master (int);
|
||||
static void __stdcall init_session ();
|
||||
void wait_pcon_fwd (void);
|
||||
void wait_pcon_fwd (bool init = true);
|
||||
friend class fhandler_pty_common;
|
||||
friend class fhandler_pty_master;
|
||||
friend class fhandler_pty_slave;
|
||||
|
Loading…
x
Reference in New Issue
Block a user