Cygwin: console: Redesign handling of special keys.
- This patch rearranges the cooperation between cons_master_thread, line_edit, and ctrl_c_handler so that only one of them operates at the same time. Since these handle Ctrl-C individually, so the signal may be sent multiple times to the process. This patch fixes the issue.
This commit is contained in:
parent
4ed502ba02
commit
d2b14c303c
|
@ -1906,7 +1906,7 @@ class fhandler_termios: public fhandler_base
|
||||||
signalled,
|
signalled,
|
||||||
not_signalled,
|
not_signalled,
|
||||||
not_signalled_but_done,
|
not_signalled_but_done,
|
||||||
not_signalled_with_cyg_reader
|
not_signalled_with_nat_reader
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1954,9 +1954,9 @@ class fhandler_termios: public fhandler_base
|
||||||
}
|
}
|
||||||
static bool path_iscygexec_a (LPCSTR n, LPSTR c);
|
static bool path_iscygexec_a (LPCSTR n, LPSTR c);
|
||||||
static bool path_iscygexec_w (LPCWSTR n, LPWSTR c);
|
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 cleanup_before_exit () {}
|
||||||
virtual void setpgid_aux (pid_t pid) {}
|
virtual void setpgid_aux (pid_t pid) {}
|
||||||
|
virtual bool need_console_handler () { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ansi_intensity
|
enum ansi_intensity
|
||||||
|
@ -2061,6 +2061,7 @@ class dev_console
|
||||||
char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command
|
char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command
|
||||||
char *cons_rapoi;
|
char *cons_rapoi;
|
||||||
bool cursor_key_app_mode;
|
bool cursor_key_app_mode;
|
||||||
|
bool disable_master_thread;
|
||||||
|
|
||||||
inline UINT get_console_cp ();
|
inline UINT get_console_cp ();
|
||||||
DWORD con_to_str (char *d, int dlen, WCHAR w);
|
DWORD con_to_str (char *d, int dlen, WCHAR w);
|
||||||
|
@ -2253,6 +2254,7 @@ private:
|
||||||
void setup_for_non_cygwin_app ();
|
void setup_for_non_cygwin_app ();
|
||||||
static void cleanup_for_non_cygwin_app (handle_set_t *p);
|
static void cleanup_for_non_cygwin_app (handle_set_t *p);
|
||||||
static void set_console_mode_to_native ();
|
static void set_console_mode_to_native ();
|
||||||
|
bool need_console_handler ();
|
||||||
|
|
||||||
friend tty_min * tty_list::get_cttyp ();
|
friend tty_min * tty_list::get_cttyp ();
|
||||||
};
|
};
|
||||||
|
@ -2489,7 +2491,6 @@ public:
|
||||||
void get_master_thread_param (master_thread_param_t *p);
|
void get_master_thread_param (master_thread_param_t *p);
|
||||||
void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
|
void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
|
||||||
void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho = m; }
|
void set_mask_flusho (bool m) { get_ttyp ()->mask_flusho = m; }
|
||||||
bool is_pty_master_with_pcon () { return get_ttyp ()->pcon_activated; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_dev_null: public fhandler_base
|
class fhandler_dev_null: public fhandler_base
|
||||||
|
|
|
@ -195,21 +195,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
|
||||||
DWORD total_read, n, i;
|
DWORD total_read, n, i;
|
||||||
INPUT_RECORD input_rec[INREC_SIZE];
|
INPUT_RECORD input_rec[INREC_SIZE];
|
||||||
|
|
||||||
bool nat_fg = false;
|
if (con.disable_master_thread)
|
||||||
bool nat_child_fg = false;
|
|
||||||
winpids pids ((DWORD) 0);
|
|
||||||
for (unsigned i = 0; i < pids.npids; i++)
|
|
||||||
{
|
|
||||||
_pinfo *pi = pids[i];
|
|
||||||
if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
|
|
||||||
&& (pi->process_state & PID_NOTCYGWIN)
|
|
||||||
&& !(pi->process_state & PID_NEW_PG))
|
|
||||||
nat_fg = true;
|
|
||||||
if (pi && pi->ctty == ttyp->ntty && pi->pgid == ttyp->getpgid ()
|
|
||||||
&& !(pi->process_state & PID_CYGPARENT))
|
|
||||||
nat_child_fg = true;
|
|
||||||
}
|
|
||||||
if (nat_fg && !nat_child_fg)
|
|
||||||
{
|
{
|
||||||
cygwait (40);
|
cygwait (40);
|
||||||
continue;
|
continue;
|
||||||
|
@ -403,6 +389,7 @@ fhandler_console::setup ()
|
||||||
con.cons_rapoi = NULL;
|
con.cons_rapoi = NULL;
|
||||||
shared_console_info->tty_min_state.is_console = true;
|
shared_console_info->tty_min_state.is_console = true;
|
||||||
con.cursor_key_app_mode = false;
|
con.cursor_key_app_mode = false;
|
||||||
|
con.disable_master_thread = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,6 +506,7 @@ fhandler_console::setup_for_non_cygwin_app ()
|
||||||
(get_ttyp ()->getpgid ()== myself->pgid) ? tty::native : tty::restore;
|
(get_ttyp ()->getpgid ()== myself->pgid) ? tty::native : tty::restore;
|
||||||
set_input_mode (conmode, &tc ()->ti, get_handle_set ());
|
set_input_mode (conmode, &tc ()->ti, get_handle_set ());
|
||||||
set_output_mode (conmode, &tc ()->ti, get_handle_set ());
|
set_output_mode (conmode, &tc ()->ti, get_handle_set ());
|
||||||
|
con.disable_master_thread = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -534,6 +522,7 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
|
||||||
(con.owner == myself->pid) ? tty::restore : tty::cygwin;
|
(con.owner == myself->pid) ? tty::restore : tty::cygwin;
|
||||||
set_output_mode (conmode, ti, p);
|
set_output_mode (conmode, ti, p);
|
||||||
set_input_mode (conmode, ti, p);
|
set_input_mode (conmode, ti, p);
|
||||||
|
con.disable_master_thread = (con.owner == myself->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the tty structure associated with a given tty number. If the
|
/* Return the tty structure associated with a given tty number. If the
|
||||||
|
@ -707,7 +696,14 @@ fhandler_console::bg_check (int sig, bool dontsignal)
|
||||||
cygwin app and other non-cygwin apps are started simultaneously
|
cygwin app and other non-cygwin apps are started simultaneously
|
||||||
in the same process group. */
|
in the same process group. */
|
||||||
if (sig == SIGTTIN)
|
if (sig == SIGTTIN)
|
||||||
set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
|
{
|
||||||
|
set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
|
||||||
|
if (con.disable_master_thread)
|
||||||
|
{
|
||||||
|
con.disable_master_thread = false;
|
||||||
|
init_console_handler (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (sig == SIGTTOU)
|
if (sig == SIGTTOU)
|
||||||
set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
|
set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
|
||||||
|
|
||||||
|
@ -1409,8 +1405,7 @@ bool
|
||||||
fhandler_console::open_setup (int flags)
|
fhandler_console::open_setup (int flags)
|
||||||
{
|
{
|
||||||
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
set_flags ((flags & ~O_TEXT) | O_BINARY);
|
||||||
if (myself->set_ctty (this, flags) && !myself->cygstarted)
|
myself->set_ctty (this, flags);
|
||||||
init_console_handler (true);
|
|
||||||
return fhandler_base::open_setup (flags);
|
return fhandler_base::open_setup (flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,10 +1414,15 @@ fhandler_console::post_open_setup (int fd)
|
||||||
{
|
{
|
||||||
/* Setting-up console mode for cygwin app started from non-cygwin app. */
|
/* Setting-up console mode for cygwin app started from non-cygwin app. */
|
||||||
if (fd == 0)
|
if (fd == 0)
|
||||||
set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
{
|
||||||
|
set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
||||||
|
con.disable_master_thread = false;
|
||||||
|
}
|
||||||
else if (fd == 1 || fd == 2)
|
else if (fd == 1 || fd == 2)
|
||||||
set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
|
||||||
|
|
||||||
|
init_console_handler (need_console_handler ());
|
||||||
|
|
||||||
fhandler_base::post_open_setup (fd);
|
fhandler_base::post_open_setup (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1446,6 +1446,7 @@ fhandler_console::close ()
|
||||||
/* Cleaning-up console mode for cygwin apps. */
|
/* Cleaning-up console mode for cygwin apps. */
|
||||||
set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
|
set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
|
||||||
set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
|
set_input_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
|
||||||
|
con.disable_master_thread = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3617,6 +3618,7 @@ fhandler_console::set_console_mode_to_native ()
|
||||||
termios *cons_ti = &cons->tc ()->ti;
|
termios *cons_ti = &cons->tc ()->ti;
|
||||||
set_input_mode (tty::native, cons_ti, cons->get_handle_set ());
|
set_input_mode (tty::native, cons_ti, cons->get_handle_set ());
|
||||||
set_output_mode (tty::native, cons_ti, cons->get_handle_set ());
|
set_output_mode (tty::native, cons_ti, cons->get_handle_set ());
|
||||||
|
con.disable_master_thread = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3639,6 +3641,7 @@ CreateProcessA_Hooked
|
||||||
gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_a (n, c);
|
gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_a (n, c);
|
||||||
if (gdb_inferior_noncygwin)
|
if (gdb_inferior_noncygwin)
|
||||||
fhandler_console::set_console_mode_to_native ();
|
fhandler_console::set_console_mode_to_native ();
|
||||||
|
init_console_handler (false);
|
||||||
return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3653,6 +3656,7 @@ CreateProcessW_Hooked
|
||||||
gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_w (n, c);
|
gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_w (n, c);
|
||||||
if (gdb_inferior_noncygwin)
|
if (gdb_inferior_noncygwin)
|
||||||
fhandler_console::set_console_mode_to_native ();
|
fhandler_console::set_console_mode_to_native ();
|
||||||
|
init_console_handler (false);
|
||||||
return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3662,6 +3666,7 @@ ContinueDebugEvent_Hooked
|
||||||
{
|
{
|
||||||
if (gdb_inferior_noncygwin)
|
if (gdb_inferior_noncygwin)
|
||||||
fhandler_console::set_console_mode_to_native ();
|
fhandler_console::set_console_mode_to_native ();
|
||||||
|
init_console_handler (false);
|
||||||
return ContinueDebugEvent_Orig (p, t, s);
|
return ContinueDebugEvent_Orig (p, t, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3929,3 +3934,9 @@ fhandler_console::close_handle_set (handle_set_t *p)
|
||||||
CloseHandle (p->output_mutex);
|
CloseHandle (p->output_mutex);
|
||||||
p->output_mutex = NULL;
|
p->output_mutex = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
fhandler_console::need_console_handler ()
|
||||||
|
{
|
||||||
|
return con.disable_master_thread;
|
||||||
|
}
|
||||||
|
|
|
@ -315,8 +315,6 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
|
||||||
termios &ti = ttyp->ti;
|
termios &ti = ttyp->ti;
|
||||||
pid_t pgid = ttyp->pgid;
|
pid_t pgid = ttyp->pgid;
|
||||||
|
|
||||||
pinfo leader (pgid);
|
|
||||||
bool cyg_leader = leader && !(leader->process_state & PID_NOTCYGWIN);
|
|
||||||
bool ctrl_c_event_sent = false;
|
bool ctrl_c_event_sent = false;
|
||||||
bool need_discard_input = false;
|
bool need_discard_input = false;
|
||||||
bool pg_with_nat = false;
|
bool pg_with_nat = false;
|
||||||
|
@ -344,24 +342,31 @@ fhandler_termios::process_sigs (char c, tty* ttyp, fhandler_termios *fh)
|
||||||
FreeConsole ();
|
FreeConsole ();
|
||||||
AttachConsole (p->dwProcessId);
|
AttachConsole (p->dwProcessId);
|
||||||
}
|
}
|
||||||
|
if (fh && p == myself)
|
||||||
|
{ /* Avoid deadlock in gdb on console. */
|
||||||
|
fh->tcflush(TCIFLUSH);
|
||||||
|
fh->release_input_mutex_if_necessary ();
|
||||||
|
}
|
||||||
/* CTRL_C_EVENT does not work for the process started with
|
/* CTRL_C_EVENT does not work for the process started with
|
||||||
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT
|
||||||
instead. */
|
instead. */
|
||||||
if (p->process_state & PID_NEW_PG)
|
if (p->process_state & PID_NEW_PG)
|
||||||
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
|
{
|
||||||
p->dwProcessId);
|
GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT,
|
||||||
else if ((!fh || !fh->is_pty_master_with_pcon () || cyg_leader)
|
p->dwProcessId);
|
||||||
&& !ctrl_c_event_sent)
|
need_discard_input = true;
|
||||||
|
}
|
||||||
|
else if (!ctrl_c_event_sent)
|
||||||
{
|
{
|
||||||
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
|
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0);
|
||||||
ctrl_c_event_sent = true;
|
ctrl_c_event_sent = true;
|
||||||
|
need_discard_input = true;
|
||||||
}
|
}
|
||||||
if (resume_pid && fh && !fh->is_console ())
|
if (resume_pid && fh && !fh->is_console ())
|
||||||
{
|
{
|
||||||
FreeConsole ();
|
FreeConsole ();
|
||||||
AttachConsole (resume_pid);
|
AttachConsole (resume_pid);
|
||||||
}
|
}
|
||||||
need_discard_input = true;
|
|
||||||
}
|
}
|
||||||
if (p && p->ctty == ttyp->ntty && p->pgid == pgid)
|
if (p && p->ctty == ttyp->ntty && p->pgid == pgid)
|
||||||
{
|
{
|
||||||
|
@ -426,8 +431,8 @@ not_a_sig:
|
||||||
ti.c_lflag &= ~FLUSHO;
|
ti.c_lflag &= ~FLUSHO;
|
||||||
return not_signalled_but_done;
|
return not_signalled_but_done;
|
||||||
}
|
}
|
||||||
bool to_cyg = cyg_reader || !pg_with_nat;
|
bool to_nat = !cyg_reader && pg_with_nat;
|
||||||
return to_cyg ? not_signalled_with_cyg_reader : not_signalled;
|
return to_nat ? not_signalled_with_nat_reader : not_signalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -479,7 +484,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
|
|
||||||
if (ti.c_iflag & ISTRIP)
|
if (ti.c_iflag & ISTRIP)
|
||||||
c &= 0x7f;
|
c &= 0x7f;
|
||||||
bool disable_eof_key = true;
|
bool disable_eof_key = false;
|
||||||
switch (process_sigs (c, get_ttyp (), this))
|
switch (process_sigs (c, get_ttyp (), this))
|
||||||
{
|
{
|
||||||
case signalled:
|
case signalled:
|
||||||
|
@ -488,8 +493,8 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
|
||||||
case not_signalled_but_done:
|
case not_signalled_but_done:
|
||||||
get_ttyp ()->output_stopped = false;
|
get_ttyp ()->output_stopped = false;
|
||||||
continue;
|
continue;
|
||||||
case not_signalled_with_cyg_reader:
|
case not_signalled_with_nat_reader:
|
||||||
disable_eof_key = false;
|
disable_eof_key = true;
|
||||||
break;
|
break;
|
||||||
default: /* Not signalled */
|
default: /* Not signalled */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1392,7 +1392,8 @@ wait_sig (VOID *)
|
||||||
sig_held = true;
|
sig_held = true;
|
||||||
break;
|
break;
|
||||||
case __SIGSETPGRP:
|
case __SIGSETPGRP:
|
||||||
init_console_handler (true);
|
if (::cygheap->ctty)
|
||||||
|
init_console_handler (::cygheap->ctty->need_console_handler ());
|
||||||
break;
|
break;
|
||||||
case __SIGTHREADEXIT:
|
case __SIGTHREADEXIT:
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue