diff options
author | Takashi Yano <takashi.yano@nifty.ne.jp> | 2019-09-08 15:58:35 +0300 |
---|---|---|
committer | Ken Brown <kbrown@cornell.edu> | 2019-09-14 15:58:35 +0300 |
commit | b088f504265018c394f7061cc4d8013856f686f1 (patch) | |
tree | 7757b8ac771092535ab6e16e40af9e4dec515b27 | |
parent | 9786b0559565616b1b35282157d9f42f239ed656 (diff) |
Cygwin: pty: Fix the behaviour of Ctrl-C in the pseudo console mode.
- When the I/O pipe is switched to the pseudo console side, the
behaviour of Ctrl-C was unstable. This rarely happens, however,
for example, shell sometimes crashes by Ctrl-C in that situation.
Furthermore, Ctrl-C was ignored if output of non-cygwin program
is redirected to pipe. This patch fixes these issues.
-rw-r--r-- | winsup/cygwin/fhandler.h | 4 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_tty.cc | 44 | ||||
-rw-r--r-- | winsup/cygwin/select.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/spawn.cc | 42 |
4 files changed, 50 insertions, 42 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index e72e11f7a..e0c56cd34 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -2187,10 +2187,6 @@ class fhandler_pty_slave: public fhandler_pty_common get_ttyp ()->mask_switch_to_pcon = mask; } void fixup_after_attach (bool native_maybe); - pid_t get_pcon_pid (void) - { - return get_ttyp ()->pcon_pid; - } bool is_line_input (void) { return get_ttyp ()->ti.c_lflag & ICANON; diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 3ffd64e21..a8821c72c 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -895,6 +895,7 @@ fhandler_pty_slave::close () termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex); if (pcon_attached_to == get_minor ()) get_ttyp ()->num_pcon_attached_slaves --; + get_ttyp ()->mask_switch_to_pcon = false; return 0; } @@ -1026,20 +1027,26 @@ fhandler_pty_slave::reset_switch_to_pcon (void) get_ttyp ()->need_clear_screen = false; } - if (ALWAYS_USE_PCON) - return; if (isHybrid) - { - this->set_switch_to_pcon (); - return; - } + this->set_switch_to_pcon (); if (get_ttyp ()->pcon_pid && get_ttyp ()->pcon_pid != myself->pid && kill (get_ttyp ()->pcon_pid, 0) == 0) /* There is a process which is grabbing pseudo console. */ return; - if (get_ttyp ()->switch_to_pcon && - get_ttyp ()->pcon_pid != myself->pid) + if (isHybrid) + { + if (ALWAYS_USE_PCON) + { + DWORD mode; + GetConsoleMode (get_handle (), &mode); + SetConsoleMode (get_handle (), mode & ~ENABLE_PROCESSED_INPUT); + } + get_ttyp ()->pcon_pid = 0; + init_console_handler (true); + return; + } + if (get_ttyp ()->switch_to_pcon) { DWORD mode; GetConsoleMode (get_handle (), &mode); @@ -1048,6 +1055,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void) } get_ttyp ()->pcon_pid = 0; get_ttyp ()->switch_to_pcon = false; + init_console_handler (true); } void @@ -1307,8 +1315,7 @@ fhandler_pty_slave::read (void *ptr, size_t& len) if (ptr) /* Indicating not tcflush(). */ { reset_switch_to_pcon (); - if (get_ttyp ()->pcon_pid != myself->pid) - mask_switch_to_pcon (true); + mask_switch_to_pcon (true); } if (is_nonblocking () || !ptr) /* Indicating tcflush(). */ @@ -1428,7 +1435,7 @@ fhandler_pty_slave::read (void *ptr, size_t& len) flags &= ~ENABLE_ECHO_INPUT; if ((get_ttyp ()->ti.c_lflag & ISIG) && !(get_ttyp ()->ti.c_iflag & IGNBRK)) - flags |= ENABLE_PROCESSED_INPUT; + flags |= ALWAYS_USE_PCON ? 0 : ENABLE_PROCESSED_INPUT; if (dwMode != flags) SetConsoleMode (get_handle (), flags); /* Read get_handle() instad of get_handle_cyg() */ @@ -2222,6 +2229,16 @@ fhandler_pty_master::write (const void *ptr, size_t len) return len; } + if (get_ttyp ()->switch_to_pcon && + (ti.c_lflag & ISIG) && + memchr (p, ti.c_cc[VINTR], len) && + get_ttyp ()->getpgid () == get_ttyp ()->pcon_pid) + { + DWORD n; + /* Send ^C to pseudo console as well */ + WriteFile (to_slave, "\003", 1, &n, 0); + } + line_edit_status status = line_edit (p++, len, ti, &ret); if (status > line_edit_signalled && status != line_edit_pipe_full) ret = -1; @@ -2875,8 +2892,10 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe) get_ttyp ()->num_pcon_attached_slaves ++; } } + if (ALWAYS_USE_PCON && pcon_attached_to == get_minor ()) + set_ishybrid_and_switch_to_pcon (get_output_handle ()); } - if (pcon_attached_to == get_minor () && (native_maybe || ALWAYS_USE_PCON)) + if (pcon_attached_to == get_minor () && native_maybe) { FlushConsoleInputBuffer (get_handle ()); DWORD mode; @@ -2891,6 +2910,7 @@ fhandler_pty_slave::fixup_after_attach (bool native_maybe) kill (get_ttyp ()->pcon_pid, 0) != 0) get_ttyp ()->pcon_pid = myself->pid; get_ttyp ()->switch_to_pcon = true; + init_console_handler(false); } } diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 4efc302df..3589ccabf 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1294,7 +1294,7 @@ pty_slave_startup (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->get_pcon_pid () != myself->pid) + if (me->read_selected) ptys->mask_switch_to_pcon (true); select_pipe_info *pi = stuff->device_specific_ptys; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 15cba3610..7c9e67303 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -261,6 +261,21 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, int res = -1; DWORD pidRestore = 0; bool attach_to_pcon = false; + pid_t ctty_pgid = 0; + + /* Search for CTTY and retrieve its PGID */ + cygheap_fdenum cfd (false); + while (cfd.next () >= 0) + if (cfd->get_major () == DEV_PTYS_MAJOR || + cfd->get_major () == DEV_CONS_MAJOR) + { + fhandler_termios *fh = (fhandler_termios *) (fhandler_base *) cfd; + if (fh->tc ()->ntty == myself->ctty) + { + ctty_pgid = fh->tc ()->getpgid (); + break; + } + } /* Check if we have been called from exec{lv}p or spawn{lv}p and mask mode to keep only the spawn mode. */ @@ -539,8 +554,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, in a console will break native processes running in the background, because the Ctrl-C event is sent to all processes in the console, unless they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */ - if (!iscygwin () && fhandler_console::exists () - && fhandler_console::tc_getpgid () != myself->pgid) + if (!iscygwin () && ctty_pgid && ctty_pgid != myself->pgid) c_flags |= CREATE_NEW_PROCESS_GROUP; refresh_cygheap (); @@ -606,33 +620,11 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, 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) + if (ptys && attach_to_pcon) ptys->fixup_after_attach (!iscygwin ()); if (!iscygwin ()) |