Takashi Yano (8): Cygwin: pty, console: Fix Ctrl-C handling for non-cygwin apps. Cygwin: pty: Pass Ctrl-Z (EOF) to non-cygwin apps with disable_pcon. Cygwin: pty: Prevent deadlock on echo output. Cygwin: pty: Revise the code to wait for completion of forwarding. Cygwin: pty: Discard input in from_master_nat pipe on signal as well. Cygwin: pty: Fix a bug in tty_min::segpgid(). Cygwin: console: Fix console mode for non-cygwin inferior of GDB. Cygwin: console: Set console mode even if stdin/stdout is redirected. winsup/cygwin/fhandler.h | 2 + winsup/cygwin/fhandler_console.cc | 67 +++++++++++++++ winsup/cygwin/fhandler_termios.cc | 47 +++++++++- winsup/cygwin/fhandler_tty.cc | 138 ++++++++++++++++-------------- winsup/cygwin/spawn.cc | 19 ++-- winsup/cygwin/tty.cc | 14 +-- winsup/cygwin/tty.h | 3 +- 7 files changed, 204 insertions(+), 86 deletions(-) -- 2.35.1
- Currently, if cat is started from cmd.exe which is started in cygwin console, Ctrl-C terminates not only cat but also cmd.exe. This also happens in pty in which pseudo console is disabled. This patch fixes the issue. --- winsup/cygwin/fhandler_console.cc | 28 +++++++++++++++++++++++ winsup/cygwin/fhandler_termios.cc | 38 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index b28dd66f5..da65c465e 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -238,6 +238,33 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) char c = (char) wc; bool processed = false; termios &ti = ttyp->ti; + pinfo pi (ttyp->getpgid ()); + if (pi && pi->ctty == ttyp->ntty + && (pi->process_state & PID_NOTCYGWIN) + && input_rec[i].EventType == KEY_EVENT && c == '\003') + { + bool not_a_sig = false; + if (!CCEQ (ti.c_cc[VINTR], c) + && !CCEQ (ti.c_cc[VQUIT], c) + && !CCEQ (ti.c_cc[VSUSP], c)) + not_a_sig = true; + if (input_rec[i].Event.KeyEvent.bKeyDown) + { + /* CTRL_C_EVENT does not work for the process started with + CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT + instead. */ + if (pi->process_state & PID_NEW_PG) + GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, + pi->dwProcessId); + else + GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0); + if (not_a_sig) + goto skip_writeback; + } + processed = true; + if (not_a_sig) + goto remove_record; + } switch (input_rec[i].EventType) { case KEY_EVENT: @@ -310,6 +337,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) processed = true; break; } +remove_record: if (processed) { /* Remove corresponding record. */ memmove (input_rec + i, input_rec + i + 1, diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index 3461d1785..fe1021520 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -147,6 +147,8 @@ tty_min::kill_pgrp (int sig) _pinfo *p = pids[i]; if (!p || !p->exists () || p->ctty != ntty || p->pgid != pgid) continue; + if (p->process_state & PID_NOTCYGWIN) + continue; if (p == myself) killself = sig != __SIGSETPGRP && !exit_state; else @@ -326,6 +328,42 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, if (ti.c_iflag & ISTRIP) c &= 0x7f; + winpids pids ((DWORD) 0); + if (get_ttyp ()->pcon_input_state_eq (tty::to_nat)) + { + bool need_discard_input = false; + for (unsigned i = 0; i < pids.npids; i++) + { + _pinfo *p = pids[i]; + if (c == '\003' && p && p->ctty == tc ()->ntty + && p->pgid == tc ()->getpgid () + && (p->process_state & PID_NOTCYGWIN)) + { + /* CTRL_C_EVENT does not work for the process started with + CREATE_NEW_PROCESS_GROUP flag, so send CTRL_BREAK_EVENT + instead. */ + if (p->process_state & PID_NEW_PG) + GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, + p->dwProcessId); + else + GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0); + need_discard_input = true; + } + } + if (need_discard_input + && !CCEQ (ti.c_cc[VINTR], c) + && !CCEQ (ti.c_cc[VQUIT], c) + && !CCEQ (ti.c_cc[VSUSP], c)) + { + if (!(ti.c_lflag & NOFLSH)) + { + eat_readahead (-1); + discard_input (); + } + ti.c_lflag &= ~FLUSHO; + continue; + } + } if (ti.c_lflag & ISIG) { int sig; -- 2.35.1
- Previously, non-cygwin app running in pty started without pseudo console support was suspended by Ctrl-Z rather than sending EOF. Even worse, suspended app could not be resumed by fg command. With this patch, Ctrl-Z (EOF for non-cygwin apps) is passed to non-cygwin app instead of suspending that app. This patch also handles Ctrl-\ (QUIT) and Ctrl-D (EOF) as well. --- winsup/cygwin/fhandler_termios.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index fe1021520..b935a70bc 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -329,6 +329,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, if (ti.c_iflag & ISTRIP) c &= 0x7f; winpids pids ((DWORD) 0); + bool need_check_sigs = get_ttyp ()->pcon_input_state_eq (tty::to_cyg); if (get_ttyp ()->pcon_input_state_eq (tty::to_nat)) { bool need_discard_input = false; @@ -349,11 +350,15 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0); need_discard_input = true; } + if (p->ctty == get_ttyp ()->ntty + && p->pgid == get_ttyp ()->getpgid () && !p->cygstarted) + need_check_sigs = true; } - if (need_discard_input - && !CCEQ (ti.c_cc[VINTR], c) + if (!CCEQ (ti.c_cc[VINTR], c) && !CCEQ (ti.c_cc[VQUIT], c) && !CCEQ (ti.c_cc[VSUSP], c)) + need_check_sigs = false; + if (need_discard_input && !need_check_sigs) { if (!(ti.c_lflag & NOFLSH)) { @@ -364,7 +369,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, continue; } } - if (ti.c_lflag & ISIG) + if ((ti.c_lflag & ISIG) && need_check_sigs) { int sig; if (CCEQ (ti.c_cc[VINTR], c)) @@ -469,7 +474,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti, } continue; } - else if (CCEQ (ti.c_cc[VEOF], c)) + else if (CCEQ (ti.c_cc[VEOF], c) && need_check_sigs) { termios_printf ("EOF"); accept_input (); -- 2.35.1
- If the slave process writes a lot of text output, doecho() can cause deadlock. This is because output_mutex is held in slave:: write() and if WriteFile() is blocked due to pipe full, doecho() tries to acquire output_mutex and gets into deadlock. With this patch, the deadlock is prevented on the sacrifice of atomicity of doecho(). --- winsup/cygwin/fhandler_tty.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 7bef6958c..7e065c46a 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -496,11 +496,9 @@ void fhandler_pty_master::doecho (const void *str, DWORD len) { ssize_t towrite = len; - acquire_output_mutex (mutex_timeout); if (!process_opost_output (echo_w, str, towrite, true, get_ttyp (), is_nonblocking ())) termios_printf ("Write to echo pipe failed, %E"); - release_output_mutex (); } int -- 2.35.1
- With this patch, the code to wait for completion of forwarding of output from non-cygwin app is revised so that it can more reliably detect the completion. --- winsup/cygwin/fhandler_tty.cc | 5 ++++- winsup/cygwin/tty.cc | 11 ++++++----- winsup/cygwin/tty.h | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 7e065c46a..7e733e49a 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -1118,7 +1118,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void) if (WaitForSingleObject (h_gdb_process, 0) == WAIT_TIMEOUT) { if (isHybrid) - get_ttyp ()->wait_pcon_fwd (false); + get_ttyp ()->wait_pcon_fwd (); } else { @@ -2705,6 +2705,9 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p) for (;;) { p->ttyp->pcon_last_time = GetTickCount (); + DWORD n; + p->ttyp->pcon_fwd_not_empty = + ::bytes_available (n, p->from_slave_nat) && n; if (!ReadFile (p->from_slave_nat, outbuf, NT_MAX_PATH, &rlen, NULL)) { termios_printf ("ReadFile for forwarding failed, %E"); diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index 789528856..da75b8dd2 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -240,6 +240,7 @@ tty::init () pcon_pid = 0; term_code_page = 0; pcon_last_time = 0; + pcon_fwd_not_empty = false; pcon_start = false; pcon_start_pid = 0; pcon_cap_checked = false; @@ -367,7 +368,7 @@ tty_min::setpgid (int pid) } void -tty::wait_pcon_fwd (bool init) +tty::wait_pcon_fwd () { /* The forwarding in pseudo console sometimes stops for 16-32 msec even if it already has data to transfer. @@ -377,11 +378,11 @@ tty::wait_pcon_fwd (bool init) thread when the last data is transfered. */ const int sleep_in_pcon = 16; const int time_to_wait = sleep_in_pcon * 2 + 1/* margine */; - if (init) - pcon_last_time = GetTickCount (); - while (GetTickCount () - pcon_last_time < time_to_wait) + int elapsed; + while (pcon_fwd_not_empty + || (elapsed = GetTickCount () - pcon_last_time) < time_to_wait) { - int tw = time_to_wait - (GetTickCount () - pcon_last_time); + int tw = pcon_fwd_not_empty ? 10 : (time_to_wait - elapsed); cygwait (tw); } } diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h index 519d7c0d5..2cd12a665 100644 --- a/winsup/cygwin/tty.h +++ b/winsup/cygwin/tty.h @@ -116,6 +116,7 @@ private: DWORD pcon_pid; UINT term_code_page; DWORD pcon_last_time; + bool pcon_fwd_not_empty; HANDLE h_pcon_write_pipe; HANDLE h_pcon_condrv_reference; HANDLE h_pcon_conhost_process; @@ -166,7 +167,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 (bool init = true); + void wait_pcon_fwd (); bool pcon_input_state_eq (xfer_dir x) { return pcon_input_state == x; } bool pcon_fg (pid_t pgid); friend class fhandler_pty_common; -- 2.35.1
- Currently, pty discards input only in from_master pipe on signal. Due to this, if pty is started without pseudo console support and start a non-cygwin process from cmd.exe, type adhead input is not discarded on signals such as Ctrl-C. This patch fixes the issue. --- winsup/cygwin/fhandler_tty.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 7e733e49a..8c9a10c23 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -438,6 +438,9 @@ fhandler_pty_master::discard_input () while (::bytes_available (bytes_in_pipe, from_master) && bytes_in_pipe) ReadFile (from_master, buf, sizeof(buf), &n, NULL); ResetEvent (input_available_event); + if (!get_ttyp ()->pcon_activated) + while (::bytes_available (bytes_in_pipe, from_master_nat) && bytes_in_pipe) + ReadFile (from_master_nat, buf, sizeof(buf), &n, NULL); get_ttyp ()->discard_input = true; ReleaseMutex (input_mutex); } -- 2.35.1
- In tty_min::setpgid(), a pointer to fhandler instance is casted to fhandler_pty_slave and accessed even if terminal is not a pty slave. This patch fixes the issue. --- winsup/cygwin/tty.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index da75b8dd2..c0015aceb 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -309,7 +309,8 @@ tty_min::setpgid (int pid) fhandler_pty_slave *ptys = NULL; cygheap_fdenum cfd (false); while (cfd.next () >= 0 && ptys == NULL) - if (cfd->get_device () == getntty ()) + if (cfd->get_device () == getntty () + && cfd->get_major () == DEV_PTYS_MAJOR) ptys = (fhandler_pty_slave *) (fhandler_base *) cfd; if (ptys) -- 2.35.1
- Currently, there is no chance to change console mode for non-cygwin inferior of GDB. With this patch, the console mode is changed to tty::native in CreateProcess() and ContinueDebugEvent() hooked in fhandler_console. --- winsup/cygwin/fhandler.h | 2 + winsup/cygwin/fhandler_console.cc | 39 +++++++++ winsup/cygwin/fhandler_tty.cc | 128 +++++++++++++++--------------- 3 files changed, 107 insertions(+), 62 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index fb4747608..4e86ab58a 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1941,6 +1941,8 @@ class fhandler_termios: public fhandler_base fh->copy_from (this); return fh; } + static bool path_iscygexec_a (LPCSTR n, LPSTR c); + static bool path_iscygexec_w (LPCWSTR n, LPWSTR c); }; enum ansi_intensity diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index da65c465e..50f350c49 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -32,6 +32,7 @@ details. */ #include "sync.h" #include "child_info.h" #include "cygwait.h" +#include "winf.h" /* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer is allocated using tmp_pathbuf!!! */ @@ -3595,10 +3596,32 @@ set_console_title (char *title) debug_printf ("title '%W'", buf); } +static bool NO_COPY gdb_inferior_noncygwin = false; +static void +set_console_mode_to_native () +{ + cygheap_fdenum cfd (false); + while (cfd.next () >= 0) + if (cfd->get_major () == DEV_CONS_MAJOR) + { + fhandler_console *cons = (fhandler_console *) (fhandler_base *) cfd; + if (cons->get_device () == cons->tc ()->getntty ()) + { + termios *cons_ti = &((tty *) cons->tc ())->ti; + fhandler_console::set_input_mode (tty::native, cons_ti, + cons->get_handle_set ()); + fhandler_console::set_output_mode (tty::native, cons_ti, + cons->get_handle_set ()); + break; + } + } +} + #define DEF_HOOK(name) static __typeof__ (name) *name##_Orig /* CreateProcess() is hooked for GDB etc. */ DEF_HOOK (CreateProcessA); DEF_HOOK (CreateProcessW); +DEF_HOOK (ContinueDebugEvent); static BOOL WINAPI CreateProcessA_Hooked @@ -3608,6 +3631,9 @@ CreateProcessA_Hooked { if (f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) mutex_timeout = 0; /* to avoid deadlock in GDB */ + gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_a (n, c); + if (gdb_inferior_noncygwin) + set_console_mode_to_native (); return CreateProcessA_Orig (n, c, pa, ta, inh, f, e, d, si, pi); } @@ -3619,9 +3645,21 @@ CreateProcessW_Hooked { if (f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) mutex_timeout = 0; /* to avoid deadlock in GDB */ + gdb_inferior_noncygwin = !fhandler_termios::path_iscygexec_w (n, c); + if (gdb_inferior_noncygwin) + set_console_mode_to_native (); return CreateProcessW_Orig (n, c, pa, ta, inh, f, e, d, si, pi); } +static BOOL WINAPI +ContinueDebugEvent_Hooked + (DWORD p, DWORD t, DWORD s) +{ + if (gdb_inferior_noncygwin) + set_console_mode_to_native (); + return ContinueDebugEvent_Orig (p, t, s); +} + void fhandler_console::fixup_after_fork_exec (bool execing) { @@ -3641,6 +3679,7 @@ fhandler_console::fixup_after_fork_exec (bool execing) /* CreateProcess() is hooked for GDB etc. */ DO_HOOK (NULL, CreateProcessA); DO_HOOK (NULL, CreateProcessW); + DO_HOOK (NULL, ContinueDebugEvent); } /* Ugly workaround to create invisible console required since Windows 7. diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 8c9a10c23..5ba50cc73 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -157,6 +157,66 @@ set_switch_to_pcon (HANDLE *in, HANDLE *out, HANDLE *err, bool iscygwin) *err = replace_err->get_output_handle_nat (); } +static bool +path_iscygexec_a_w (LPCSTR na, LPSTR ca, LPCWSTR nw, LPWSTR cw) +{ + path_conv path; + tmp_pathbuf tp; + char *prog =tp.c_get (); + if (na) + { + __small_sprintf (prog, "%s", na); + find_exec (prog, path); + } + else if (nw) + { + __small_sprintf (prog, "%W", nw); + find_exec (prog, path); + } + else + { + if (ca) + __small_sprintf (prog, "%s", ca); + else if (cw) + __small_sprintf (prog, "%W", cw); + else + return true; + char *p = prog; + char *p1; + do + if ((p1 = strchr (p, ' ')) || (p1 = p + strlen (p))) + { + p = p1; + if (*p == ' ') + { + *p = '\0'; + find_exec (prog, path); + *p = ' '; + p ++; + } + else if (*p == '\0') + find_exec (prog, path); + } + while (!path.exists() && *p); + } + const char *argv[] = {"", NULL}; /* Dummy */ + av av1; + av1.setup ("", path, "", 1, argv, false); + return path.iscygexec (); +} + +bool +fhandler_termios::path_iscygexec_a (LPCSTR n, LPSTR c) +{ + return path_iscygexec_a_w (n, c, NULL, NULL); +} + +bool +fhandler_termios::path_iscygexec_w (LPCWSTR n, LPWSTR c) +{ + return path_iscygexec_a_w (NULL, NULL, n, c); +} + static bool atexit_func_registered = false; static bool debug_process = false; @@ -220,37 +280,9 @@ CreateProcessA_Hooked siov->hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); siov->hStdError = GetStdHandle (STD_ERROR_HANDLE); } - 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 = strchr (p, ' ')) || (p1 = p + strlen (p))) - { - p = p1; - if (*p == ' ') - { - *p = '\0'; - find_exec (prog, path); - *p = ' '; - p ++; - } - else if (*p == '\0') - find_exec (prog, path); - } - while (!path.exists() && *p); - } - const char *argv[] = {"", NULL}; /* Dummy */ - av av1; - av1.setup ("", path, "", 1, argv, false); + bool path_iscygexec = fhandler_termios::path_iscygexec_a (n, c); set_switch_to_pcon (&siov->hStdInput, &siov->hStdOutput, &siov->hStdError, - path.iscygexec ()); + 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, @@ -259,7 +291,7 @@ CreateProcessA_Hooked debug_process = !!(f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)); if (debug_process) mutex_timeout = 0; /* to avoid deadlock in GDB */ - if (!atexit_func_registered && !path.iscygexec ()) + if (!atexit_func_registered && !path_iscygexec) { atexit (atexit_func); atexit_func_registered = true; @@ -286,37 +318,9 @@ CreateProcessW_Hooked siov->hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); siov->hStdError = GetStdHandle (STD_ERROR_HANDLE); } - 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 = strchr (p, ' ')) || (p1 = p + strlen (p))) - { - p = p1; - if (*p == ' ') - { - *p = '\0'; - find_exec (prog, path); - *p = ' '; - p ++; - } - else if (*p == '\0') - find_exec (prog, path); - } - while (!path.exists() && *p); - } - const char *argv[] = {"", NULL}; /* Dummy */ - av av1; - av1.setup ("", path, "", 1, argv, false); + bool path_iscygexec = fhandler_termios::path_iscygexec_w (n, c); set_switch_to_pcon (&siov->hStdInput, &siov->hStdOutput, &siov->hStdError, - path.iscygexec ()); + 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, @@ -325,7 +329,7 @@ CreateProcessW_Hooked debug_process = !!(f & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)); if (debug_process) mutex_timeout = 0; /* to avoid deadlock in GDB */ - if (!atexit_func_registered && !path.iscygexec ()) + if (!atexit_func_registered && !path_iscygexec) { atexit (atexit_func); atexit_func_registered = true; -- 2.35.1
- When non-cygwin app is started in console, console mode is set to tty::native. However, if stdin is redirected, current code does not set the input mode of the console. In this case, if the app opens "CONIN$", the console mode will not be appropriate for non-cygwin app. This patch fixes the issue. Addresses: https://github.com/GitCredentialManager/git-credential-manager/issues/576 --- winsup/cygwin/spawn.cc | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 81dba5a94..a7e25cc20 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -627,23 +627,18 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, } else if (fh && fh->get_major () == DEV_CONS_MAJOR) { - fhandler_console *cons = (fhandler_console *) fh; - if (!iscygwin ()) + if (!iscygwin () && cons_native == NULL) { - if (cons_native == NULL) - { - cons_native = cons; - cons_ti = &((tty *)cons->tc ())->ti; - cons_owner = cons->get_owner (); - } + fhandler_console *cons = (fhandler_console *) fh; + cons_native = cons; + cons_ti = &((tty *)cons->tc ())->ti; + cons_owner = cons->get_owner (); tty::cons_mode conmode = (ctty_pgid && ctty_pgid == myself->pgid) ? tty::native : tty::restore; - if (fd == 0) - fhandler_console::set_input_mode (conmode, + fhandler_console::set_input_mode (conmode, cons_ti, cons->get_handle_set ()); - else if (fd == 1 || fd == 2) - fhandler_console::set_output_mode (conmode, + fhandler_console::set_output_mode (conmode, cons_ti, cons->get_handle_set ()); } } -- 2.35.1