[PATCH v7 4/7] Cygwin: pty: Apply line_edit() for transferred input to to_cyg
Johannes Schindelin
Johannes.Schindelin@gmx.de
Fri Mar 27 14:50:06 GMT 2026
Hi Takashi,
This is a nice fix for a subtle problem. I have a few observations,
mostly about the commit message and one edge case.
On Wed, 25 Mar 2026, Takashi Yano wrote:
> The typeahead input while non-cygwin app is running is put into
> the pipe directly by transfer_input(). So, if the shell sets the
> terminal canonical mode, erase char (such as backspace) fails to
> erase chars transferred by transfer_input(). With this patch,
> transferred input in the pipe is read and passed to line_edit()
> to handle erase chars such as VERASE, VKILL, etc.
The commit message is too terse for a change of this complexity. It
describes _what_ is broken but not _why_ the fix has to look the way
it does, nor the synchronization protocol you are introducing.
I think the message should cover at least these three things:
(a) Why the transferred bytes need `line_edit()` processing: when
keystrokes travel through the nat pipe (during a native process
session), they bypass POSIX line discipline entirely. When they are
transferred back to the cyg pipe at cleanup, they arrive as raw bytes.
If the terminal is in canonical mode at that point, VERASE/VKILL
characters in those raw bytes will not erase anything because
`line_edit()` was never applied to them.
(b) Why the forward thread is the right place to call `line_edit()`:
it runs in the master process alongside `master::write()`, sharing
access to the readahead buffer and `line_edit()` state. Calling
`line_edit()` from the slave side (where `transfer_input()` runs)
would not work because `line_edit()` state belongs to the master.
(c) The synchronization protocol: `transfer_input()` signals the
event, then spin-waits for the forward thread to clear it, then
proceeds.
Something like this might work:
When keystrokes travel through the nat pipe during a native process
session, they bypass POSIX line discipline entirely. When they are
transferred back to the cyg pipe at cleanup (via
`transfer_input(to_cyg)`), they arrive as raw bytes. If the
terminal is in canonical mode at that point, VERASE and VKILL
characters in those raw bytes have no effect because `line_edit()`
was never applied to them. The result: backspace typed while a
native process was running fails to erase the preceding character
once the input reaches bash's readline.
The fix applies `line_edit()` to the transferred bytes before they
reach the reading process. The right place to do this is the
master's forward thread (`pty_master_fwd_thread()`), because it
runs in the master process alongside `fhandler_pty_master::write()`
and shares access to the readahead buffer and `line_edit()` state.
Calling `line_edit()` from the slave (where `transfer_input()` runs)
would not work because that state belongs to the master.
To coordinate: `transfer_input(to_cyg)` writes the raw bytes to
the cyg pipe's slave end (`to_slave`), then signals a new
cross-process event (`input_transferred_to_cyg`) and spin-waits
for the forward thread to clear it. The forward thread is converted
from synchronous to overlapped I/O so it can wait on both the
`from_slave_nat` read completion and the transfer event
simultaneously. When the event fires, it reads the transferred
bytes from the cyg pipe's master end (`from_master`), processes
them through `line_edit()`, and clears the event.
The spin-wait in `transfer_input()` holds `input_mutex` (from its
caller), which blocks `fhandler_pty_master::write()` from injecting
new keystrokes until the forward thread has finished applying
`line_edit()` to the transferred bytes.
Note: _You_ are the domain expert on this, and I am quite far, still from
understanding the ins and outs of your design, as demonstrated by my
original patch series that started this thread. So I can only depend on
you to fix any mistakes my lack of understanding introduced in that
suggested commit message.
>
> Fixes: 10d083c745dd ("Cygwin: pty: Inherit typeahead data between two input pipes.")
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> Reviewed-by:
> ---
> winsup/cygwin/fhandler/pty.cc | 135 +++++++++++++++++-------
> winsup/cygwin/local_includes/fhandler.h | 10 +-
> winsup/cygwin/local_includes/tty.h | 1 +
> 3 files changed, 105 insertions(+), 41 deletions(-)
>
> diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
> index 72a8ba140..2a0e0d2f7 100644
> --- a/winsup/cygwin/fhandler/pty.cc
> +++ b/winsup/cygwin/fhandler/pty.cc
> @@ -210,6 +210,7 @@ atexit_func (void)
> {
> ptys->get_handle_nat (),
> ptys->get_input_available_event (),
> + ptys->input_transferred_to_cyg,
> ptys->input_mutex,
> ptys->pipe_sw_mutex
> };
> @@ -739,7 +740,7 @@ fhandler_pty_slave::open (int flags, mode_t)
> {
> &from_master_nat_local, &input_available_event, &input_mutex, &inuse,
> &output_mutex, &to_master_nat_local, &pty_owner, &to_master_local,
> - &from_master_local, &pipe_sw_mutex,
> + &from_master_local, &pipe_sw_mutex, &input_transferred_to_cyg,
> NULL
> };
>
> @@ -779,6 +780,12 @@ fhandler_pty_slave::open (int flags, mode_t)
> errmsg = "open input event failed, %E";
> goto err;
> }
> + shared_name (buf, INPUT_TRANSFERRED_EVENT, get_minor ());
> + if (!(input_transferred_to_cyg = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
> + {
> + errmsg = "open input transferred event failed, %E";
> + goto err;
> + }
>
> /* FIXME: Needs a method to eliminate tty races */
> {
> @@ -993,6 +1000,8 @@ fhandler_pty_slave::close (int flag)
> termios_printf ("CloseHandle (inuse), %E");
> if (!ForceCloseHandle (input_available_event))
> termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
> + if (!ForceCloseHandle (input_transferred_to_cyg))
> + termios_printf ("CloseHandle (input_transferred_to_cyg<%p>), %E", input_transferred_to_cyg);
> if (!ForceCloseHandle (get_output_handle_nat ()))
> termios_printf ("CloseHandle (get_output_handle_nat ()<%p>), %E",
> get_output_handle_nat ());
> @@ -1101,7 +1110,8 @@ fhandler_pty_slave::reset_switch_to_nat_pipe (void)
> WaitForSingleObject (input_mutex, mutex_timeout);
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_cyg, get_handle_nat (), get_ttyp (),
> - input_available_event);
> + input_available_event,
> + input_transferred_to_cyg);
> release_attach_mutex ();
> ReleaseMutex (input_mutex);
> }
> @@ -1277,14 +1287,14 @@ fhandler_pty_slave::mask_switch_to_nat_pipe (bool mask, bool xfer)
> {
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_cyg, get_handle_nat (), get_ttyp (),
> - input_available_event);
> + input_available_event, input_transferred_to_cyg);
> release_attach_mutex ();
> }
> else if (!mask && get_ttyp ()->pty_input_state_eq (tty::to_cyg))
> {
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_nat, get_handle (), get_ttyp (),
> - input_available_event);
> + input_available_event, input_transferred_to_cyg);
> release_attach_mutex ();
> }
> }
> @@ -1862,11 +1872,15 @@ fhandler_pty_slave::fch_open_handles (bool chown)
> shared_name (buf, INPUT_AVAILABLE_EVENT, get_minor ());
> input_available_event = OpenEvent (READ_CONTROL | write_access,
> TRUE, buf);
> + shared_name (buf, INPUT_TRANSFERRED_EVENT, get_minor ());
> + input_transferred_to_cyg = OpenEvent (READ_CONTROL | write_access,
> + TRUE, buf);
> output_mutex = get_ttyp ()->open_output_mutex (write_access);
> input_mutex = get_ttyp ()->open_input_mutex (write_access);
> pipe_sw_mutex = get_ttyp ()->open_mutex (PIPE_SW_MUTEX, write_access);
> inuse = get_ttyp ()->open_inuse (write_access);
> - if (!input_available_event || !output_mutex || !input_mutex || !inuse)
> + if (!input_available_event || !output_mutex || !input_mutex || !inuse
> + || !input_transferred_to_cyg)
> {
> __seterrno ();
> return false;
> @@ -1883,11 +1897,13 @@ fhandler_pty_slave::fch_set_sd (security_descriptor &sd, bool chown)
>
> get_object_sd (input_available_event, sd_old);
> if (!set_object_sd (input_available_event, sd, chown)
> + && !set_object_sd (input_transferred_to_cyg, sd, chown)
> && !set_object_sd (output_mutex, sd, chown)
> && !set_object_sd (input_mutex, sd, chown)
> && !set_object_sd (inuse, sd, chown))
> return 0;
> set_object_sd (input_available_event, sd_old, chown);
> + set_object_sd (input_transferred_to_cyg, sd_old, chown);
> set_object_sd (output_mutex, sd_old, chown);
> set_object_sd (input_mutex, sd_old, chown);
> set_object_sd (inuse, sd_old, chown);
> @@ -1900,6 +1916,7 @@ void
> fhandler_pty_slave::fch_close_handles ()
> {
> close_maybe (input_available_event);
> + close_maybe (input_transferred_to_cyg);
> close_maybe (output_mutex);
> close_maybe (input_mutex);
> close_maybe (inuse);
> @@ -2151,6 +2168,9 @@ fhandler_pty_master::close (int flag)
> if (!ForceCloseHandle (input_available_event))
> termios_printf ("CloseHandle (input_available_event<%p>), %E",
> input_available_event);
> + if (!ForceCloseHandle (input_transferred_to_cyg))
> + termios_printf ("CloseHandle (input_transferred_to_cyg<%p>), %E",
> + input_transferred_to_cyg);
>
> /* The from_master must be closed last so that the same pty is not
> allocated before cleaning up the other corresponding instances. */
> @@ -2248,7 +2268,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
> acquire_attach_mutex (mutex_timeout);
> fhandler_pty_slave::transfer_input (tty::to_nat, from_master,
> get_ttyp (),
> - input_available_event);
> + input_available_event,
> + input_transferred_to_cyg);
> release_attach_mutex ();
> ReleaseMutex (input_mutex);
> }
> @@ -2346,7 +2367,8 @@ fhandler_pty_master::write (const void *ptr, size_t len)
> {
> acquire_attach_mutex (mutex_timeout);
> fhandler_pty_slave::transfer_input (tty::to_nat, from_master,
> - get_ttyp (), input_available_event);
> + get_ttyp (), input_available_event,
> + input_transferred_to_cyg);
> release_attach_mutex ();
> }
>
> @@ -2707,6 +2729,24 @@ reply:
> return 0;
> }
>
> +void
> +fhandler_pty_master::apply_line_edit_to_transferred_input ()
> +{
> + const size_t pipesize = fhandler_pty_common::pipesize;
> + char buf[pipesize];
> + DWORD n;
> + ReadFile (from_master, buf, pipesize, &n, NULL);
One edge case: this reads up to `pipesize` bytes in a single
`ReadFile()`. If `transfer_input()` wrote more than that (unlikely
with typeahead, but possible in principle), the remaining bytes stay
in the pipe. The forward thread would pick them up on the next
iteration via the regular `ReadFile()` path, but _without_
`line_edit()` processing. In practice `pipesize` is 128 KB which is
large enough that this is unlikely to matter, but it might be worth a
comment explaining the assumption, or a loop to drain all pending
bytes through `line_edit()`.
Also, `char buf[pipesize]` puts 128 KB on the stack. That is quite
large for a stack allocation. A heap allocation (or a smaller
fixed-size buffer in a loop) would be safer.
> + char *p = buf;
> + while (n)
> + {
> + ssize_t ret;
> + line_edit (p, n, get_ttyp ()->ti, &ret);
> + n -= ret;
> + p += ret;
> + }
> + SetEvent (input_available_event);
> +}
> +
> static DWORD
> pty_master_thread (VOID *arg)
> {
> @@ -2891,19 +2931,34 @@ fhandler_pty_master::pty_master_fwd_thread (const master_fwd_thread_param_t *p)
> char *outbuf = tp.c_get ();
> char *mbbuf = tp.c_get ();
> static mbstate_t mbp;
> + OVERLAPPED ov = {0, };
> + ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
> + HANDLE w[2] = {ov.hEvent, p->input_transferred_to_cyg};
>
> termios_printf ("Started.");
> for (;;)
> {
> p->ttyp->fwd_last_time = GetTickCount64 ();
> - DWORD n;
> - p->ttyp->fwd_not_empty =
> - ::bytes_available (n, p->from_slave_nat) && n;
> - if (!ReadFile (p->from_slave_nat, outbuf, NT_MAX_PATH, &rlen, NULL))
> + if (!ReadFile (p->from_slave_nat, outbuf, NT_MAX_PATH, NULL, &ov)
> + && GetLastError () != ERROR_IO_PENDING)
> {
> termios_printf ("ReadFile for forwarding failed, %E");
> break;
> }
> +wait_event:
> + switch (WaitForMultipleObjects (2, w, FALSE, INFINITE))
> + {
> + case WAIT_OBJECT_0:
> + GetOverlappedResult (p->from_slave_nat, &ov, &rlen, FALSE);
> + ResetEvent (ov.hEvent);
> + break;
> + case WAIT_OBJECT_0 + 1:
> + p->master->apply_line_edit_to_transferred_input ();
> + ResetEvent (p->input_transferred_to_cyg);
> + goto wait_event;
> + default:
> + goto wait_event;
> + }
The overlapped I/O conversion looks correct: waiting on both
`ov.hEvent` and `input_transferred_to_cyg` is the right approach.
However, the `default:` case silently retries via `goto wait_event`.
If `WaitForMultipleObjects()` returns `WAIT_FAILED` due to a
persistent error (e.g. a bad handle), this becomes an infinite
spin-loop with no diagnostic. A `debug_printf()` before the `goto`
would make such a situation much easier to diagnose.
> if (p->ttyp->stop_fwd_thread)
> break;
> ssize_t wlen = rlen;
> @@ -3029,7 +3084,8 @@ fhandler_pty_master::setup ()
> char pipename[sizeof ("ptyNNNN-from-master-nat")];
> __small_sprintf (pipename, "pty%d-to-master-nat", unit);
> res = fhandler_pipe::create (&sec_none, &from_slave_nat, &to_master_nat,
> - fhandler_pty_common::pipesize, pipename, 0);
> + fhandler_pty_common::pipesize, pipename,
> + FILE_FLAG_OVERLAPPED);
> if (res)
> {
> errstr = "output pipe for non-cygwin apps";
> @@ -3090,6 +3146,10 @@ fhandler_pty_master::setup ()
> &sa, TRUE))
> || GetLastError () == ERROR_ALREADY_EXISTS)
> goto err;
> + if (!(input_transferred_to_cyg = t.get_event (errstr = INPUT_TRANSFERRED_EVENT,
> + &sa, TRUE))
> + || GetLastError () == ERROR_ALREADY_EXISTS)
> + goto err;
>
> char buf[MAX_PATH];
> errstr = shared_name (buf, OUTPUT_MUTEX, unit);
> @@ -3167,6 +3227,7 @@ err:
> close_maybe (get_handle ());
> close_maybe (get_output_handle ());
> close_maybe (input_available_event);
> + close_maybe (input_transferred_to_cyg);
> close_maybe (output_mutex);
> close_maybe (input_mutex);
> close_maybe (from_master_nat);
> @@ -3978,6 +4039,8 @@ fhandler_pty_master::get_master_fwd_thread_param (master_fwd_thread_param_t *p)
> p->from_slave_nat = from_slave_nat;
> p->output_mutex = output_mutex;
> p->ttyp = get_ttyp ();
> + p->input_transferred_to_cyg = input_transferred_to_cyg;
> + p->master = this;
> SetEvent (thread_param_copied_event);
> }
>
> @@ -3985,7 +4048,8 @@ fhandler_pty_master::get_master_fwd_thread_param (master_fwd_thread_param_t *p)
> #define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
> void
> fhandler_pty_slave::transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
> - HANDLE input_available_event)
> + HANDLE input_available_event,
> + HANDLE input_transferred_to_cyg)
> {
> HANDLE to;
> if (dir == tty::to_nat)
> @@ -4107,26 +4171,8 @@ fhandler_pty_slave::transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
> ptr = mbbuf;
> len = nlen;
> }
> - /* Call WriteFile() line by line */
> - char *p0 = ptr;
> - char *p_cr = (char *) memchr (p0, '\r', len - (p0 - ptr));
> - char *p_lf = (char *) memchr (p0, '\n', len - (p0 - ptr));
> - while (p_cr || p_lf)
> - {
> - char *p1 =
> - p_cr ? (p_lf ? ((p_cr + 1 == p_lf)
> - ? p_lf : min(p_cr, p_lf)) : p_cr) : p_lf;
> - *p1 = '\n';
> - n = p1 - p0 + 1;
> - if (n && WriteFile (to, p0, n, &n, NULL) && n)
> - transfered = true;
> - p0 = p1 + 1;
> - p_cr = (char *) memchr (p0, '\r', len - (p0 - ptr));
> - p_lf = (char *) memchr (p0, '\n', len - (p0 - ptr));
> - }
> - n = len - (p0 - ptr);
> - if (n && WriteFile (to, p0, n, &n, NULL) && n)
> - transfered = true;
> + if (len && WriteFile (to, ptr, len, &n, NULL) && n)
> + transfered = true;;
> }
> }
> else
> @@ -4165,13 +4211,17 @@ fhandler_pty_slave::transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
> }
> CloseHandle (to);
>
> + ttyp->pty_input_state = dir;
> /* Fix input_available_event which indicates availability in cyg pipe. */
> if (dir == tty::to_nat) /* all data is transfered to nat pipe,
> so no data available in cyg pipe. */
> ResetEvent (input_available_event);
> else if (transfered) /* There is data transfered to cyg pipe. */
> - SetEvent (input_available_event);
> - ttyp->pty_input_state = dir;
> + {
> + SetEvent (input_transferred_to_cyg);
> + while (IsEventSignalled (input_transferred_to_cyg))
> + yield ();
This spin-wait runs while the slave holds `input_mutex` (acquired by
the caller of `transfer_input()`). During this spin, `master::write()`
cannot acquire `input_mutex`, so new keystrokes stall until the
forward thread finishes processing. I believe that is intentional (the
transfer must complete atomically before new input arrives), but it
would be good to document that deliberate blocking in the commit
message or in a comment next to the loop.
Ciao,
Johannes
> + }
> ttyp->discard_input = false;
> }
>
> @@ -4191,6 +4241,9 @@ fhandler_pty_slave::get_duplicated_handle_set (handle_set_t *p)
> DuplicateHandle (GetCurrentProcess (), input_available_event,
> GetCurrentProcess (), &p->input_available_event,
> 0, 0, DUPLICATE_SAME_ACCESS);
> + DuplicateHandle (GetCurrentProcess (), input_transferred_to_cyg,
> + GetCurrentProcess (), &p->input_transferred_to_cyg,
> + 0, 0, DUPLICATE_SAME_ACCESS);
> DuplicateHandle (GetCurrentProcess (), input_mutex,
> GetCurrentProcess (), &p->input_mutex,
> 0, 0, DUPLICATE_SAME_ACCESS);
> @@ -4206,6 +4259,8 @@ fhandler_pty_slave::close_handle_set (handle_set_t *p)
> p->from_master_nat = NULL;
> CloseHandle (p->input_available_event);
> p->input_available_event = NULL;
> + CloseHandle (p->input_transferred_to_cyg);
> + p->input_transferred_to_cyg = NULL;
> CloseHandle (p->input_mutex);
> p->input_mutex = NULL;
> CloseHandle (p->pipe_sw_mutex);
> @@ -4241,7 +4296,7 @@ fhandler_pty_slave::setup_for_non_cygwin_app (bool nopcon,
> WaitForSingleObject (input_mutex, mutex_timeout);
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_nat, get_handle (), get_ttyp (),
> - input_available_event);
> + input_available_event, input_transferred_to_cyg);
> release_attach_mutex ();
> ReleaseMutex (input_mutex);
> }
> @@ -4263,7 +4318,8 @@ fhandler_pty_slave::cleanup_for_non_cygwin_app (handle_set_t *p, tty *ttyp,
> WaitForSingleObject (p->input_mutex, mutex_timeout);
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_cyg, p->from_master_nat, ttyp,
> - p->input_available_event);
> + p->input_available_event,
> + p->input_transferred_to_cyg);
> release_attach_mutex ();
> ReleaseMutex (p->input_mutex);
> }
> @@ -4289,7 +4345,7 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
> WaitForSingleObject (input_mutex, mutex_timeout);
> acquire_attach_mutex (mutex_timeout);
> transfer_input (tty::to_nat, get_handle (), get_ttyp (),
> - input_available_event);
> + input_available_event, input_transferred_to_cyg);
> release_attach_mutex ();
> ReleaseMutex (input_mutex);
> }
> @@ -4315,7 +4371,8 @@ fhandler_pty_slave::setpgid_aux (pid_t pid)
> }
> else
> acquire_attach_mutex (mutex_timeout);
> - transfer_input (tty::to_cyg, from, get_ttyp (), input_available_event);
> + transfer_input (tty::to_cyg, from, get_ttyp (), input_available_event,
> + input_transferred_to_cyg);
> if (attach_restore)
> resume_from_temporarily_attach (resume_pid);
> else
> diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
> index 16f55b4f7..facc3c44c 100644
> --- a/winsup/cygwin/local_includes/fhandler.h
> +++ b/winsup/cygwin/local_includes/fhandler.h
> @@ -2012,6 +2012,7 @@ class fhandler_termios: public fhandler_base
> {
> HANDLE from_master_nat;
> HANDLE input_available_event;
> + HANDLE input_transferred_to_cyg;
> HANDLE input_mutex;
> HANDLE pipe_sw_mutex;
> };
> @@ -2385,13 +2386,14 @@ class fhandler_pty_common: public fhandler_termios
> fhandler_pty_common ()
> : fhandler_termios (),
> output_mutex (NULL), input_mutex (NULL), pipe_sw_mutex (NULL),
> - input_available_event (NULL)
> + input_available_event (NULL), input_transferred_to_cyg (NULL)
> {
> pc.file_attributes (FILE_ATTRIBUTE_NORMAL);
> }
> static const unsigned pipesize = 128 * 1024;
> HANDLE output_mutex, input_mutex, pipe_sw_mutex;
> HANDLE input_available_event;
> + HANDLE input_transferred_to_cyg;
>
> bool use_archetype () const {return true;}
> DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
> @@ -2514,7 +2516,8 @@ class fhandler_pty_slave: public fhandler_pty_common
> void setup_locale (void);
> void create_invisible_console (void);
> static void transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
> - HANDLE input_available_event);
> + HANDLE input_available_event,
> + HANDLE input_transferred_to_cyg);
> HANDLE get_input_available_event (void) { return input_available_event; }
> bool pcon_activated (void) { return get_ttyp ()->pcon_activated; }
> void cleanup_before_exit ();
> @@ -2549,8 +2552,10 @@ public:
> struct master_fwd_thread_param_t {
> HANDLE to_master;
> HANDLE from_slave_nat;
> + HANDLE input_transferred_to_cyg;
> HANDLE output_mutex;
> tty *ttyp;
> + fhandler_pty_master *master;
> };
> private:
> int pktmode; // non-zero if pty in a packet mode.
> @@ -2627,6 +2632,7 @@ public:
> void get_master_thread_param (master_thread_param_t *p);
> void get_master_fwd_thread_param (master_fwd_thread_param_t *p);
> bool need_send_ctrl_c_event ();
> + void apply_line_edit_to_transferred_input ();
> };
>
> class fhandler_dev_null: public fhandler_base
> diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h
> index 9485e24c5..cd1e202f1 100644
> --- a/winsup/cygwin/local_includes/tty.h
> +++ b/winsup/cygwin/local_includes/tty.h
> @@ -18,6 +18,7 @@ details. */
> /* Input/Output/ioctl events */
>
> #define INPUT_AVAILABLE_EVENT "cygtty.input.avail"
> +#define INPUT_TRANSFERRED_EVENT "cygtty.input.xfer"
> #define OUTPUT_MUTEX "cygtty.output.mutex"
> #define INPUT_MUTEX "cygtty.input.mutex"
> #define PIPE_SW_MUTEX "cygtty.pipe_sw.mutex"
> --
> 2.51.0
>
>
More information about the Cygwin-patches
mailing list