diff options
author | Egor Duda <deo@logos-m.ru> | 2001-03-04 18:34:25 +0300 |
---|---|---|
committer | Egor Duda <deo@logos-m.ru> | 2001-03-04 18:34:25 +0300 |
commit | 306c4b6737136c7bb45228c284502eb643ec95ac (patch) | |
tree | 88b3eeaefe560eb41d42081a5648a15a40ec6eea /winsup | |
parent | 0312ede431278fb8a0aa6db9ae201d928d3b0055 (diff) |
* fhandler.h (class fhandler_tty_common): New mutex and event to
syncronize input on master tty with slave tty.
* fhandler_tty.cc (fhandler_pty_master::accept_input): Use them to
syncronize with slave.
* fhandler_tty.cc (fhandler_tty_slave::read): Use input mutex and
event to syncronize with master. Do not limit amount of data read
from master to vmin value. Interrupt on signal and return already
read data, if any.
* fhandler_tty.cc (fhandler_tty_slave::open): Handle input mutex and
event.
* fhandler_tty.cc (fhandler_tty_common::close): Ditto.
* fhandler_tty.cc (fhandler_tty_common::set_close_on_exec): Ditto.
* fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Ditto.
* fhandler_tty.cc (fhandler_tty_common::dup): Ditto.
* tty.h (tty::open_input_mutex): New function.
* tty.cc (tty::common_init): Create input mutex and event.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 19 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_tty.cc | 214 | ||||
-rw-r--r-- | winsup/cygwin/tty.cc | 12 | ||||
-rw-r--r-- | winsup/cygwin/tty.h | 8 |
5 files changed, 188 insertions, 68 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3e6b8b351..35b7fa5df 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2001-03-04 Egor Duda <deo@logos-m.ru> + + * fhandler.h (class fhandler_tty_common): New mutex and event to + syncronize input on master tty with slave tty. + * fhandler_tty.cc (fhandler_pty_master::accept_input): Use them to + syncronize with slave. + * fhandler_tty.cc (fhandler_tty_slave::read): Use input mutex and + event to syncronize with master. Do not limit amount of data read + from master to vmin value. Interrupt on signal and return already + read data, if any. + * fhandler_tty.cc (fhandler_tty_slave::open): Handle input mutex and + event. + * fhandler_tty.cc (fhandler_tty_common::close): Ditto. + * fhandler_tty.cc (fhandler_tty_common::set_close_on_exec): Ditto. + * fhandler_tty.cc (fhandler_tty_common::fixup_after_fork): Ditto. + * fhandler_tty.cc (fhandler_tty_common::dup): Ditto. + * tty.h (tty::open_input_mutex): New function. + * tty.cc (tty::common_init): Create input mutex and event. + Fri Mar 2 13:32:00 2001 Corinna Vinschen <corinna@vinschen.de> * dir.cc (readdir): Fix creating path in symlink check. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 3607b3b28..73aa294a6 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -707,7 +707,8 @@ public: // Ioctl() request in tty::cmd/arg. HANDLE ioctl_done_event; // Raised by master on ioctl() completion. // Ioctl() status in tty::ioctl_retval. - HANDLE output_mutex; + HANDLE output_mutex, input_mutex; + HANDLE input_available_event; HANDLE inuse; // used to indicate that a tty is in use diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 01a5a9691..c3165285e 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -167,22 +167,21 @@ fhandler_pty_master::accept_input () { DWORD written; DWORD n; - const char dummy[1] = {'X'}; - const char *buf; + DWORD rc; + + rc = WaitForSingleObject (input_mutex, INFINITE); n = get_ttyp ()->read_retval = eat_readahead (-1); - if (n != 0) - buf = rabuf; - else + if ( n != 0 ) { - n = 1; - buf = dummy; - termios_printf ("sending EOF to slave"); + termios_printf ("about to write %d chars to slave", n); + rc = WriteFile (get_output_handle (), rabuf, n, &written, NULL); } - termios_printf ("about to write %d chars to slave", n); - if (!WriteFile (get_output_handle (), buf, n, &written, NULL)) - return -1; + else + termios_printf ("sending EOF to slave"); + SetEvent (input_available_event); + ReleaseMutex (input_mutex); return get_ttyp ()->read_retval; } @@ -459,6 +458,19 @@ fhandler_tty_slave::open (const char *, int flags, mode_t) __seterrno (); return 0; } + if (!(input_mutex = get_ttyp()->open_input_mutex (TRUE))) + { + termios_printf ("open input mutex failed, %E"); + __seterrno (); + return 0; + } + __small_sprintf (buf, INPUT_AVAILABLE_EVENT, ttynum); + if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf))) + { + termios_printf ("open input event failed, %E"); + __seterrno (); + return 0; + } /* The ioctl events may or may not exist. See output_done_event, above. */ @@ -599,29 +611,90 @@ fhandler_tty_slave::read (void *ptr, size_t len) int totalread = 0; int vmin = INT_MAX; int vtime = 0; /* Initialized to prevent -Wuninitialized warning */ + size_t readlen; + DWORD bytes_in_pipe; char buf[INP_BUFFER_SIZE]; + DWORD time_to_wait; + DWORD rc; + HANDLE w4[2]; - termios_printf("read(%x, %d) handle %d", ptr, len, get_handle ()); + termios_printf ("read(%x, %d) handle %d", ptr, len, get_handle ()); if (!(get_ttyp ()->ti.c_lflag & ICANON)) { - vmin = get_ttyp ()->ti.c_cc[VMIN]; + vmin = min (INP_BUFFER_SIZE, get_ttyp ()->ti.c_cc[VMIN]); vtime = get_ttyp ()->ti.c_cc[VTIME]; + if (vmin < 0) vmin = 0; + if (vtime < 0) vtime = 0; + if (vmin == 0) + time_to_wait = INFINITE; + else + time_to_wait = (vtime == 0 ? INFINITE : 10 * vtime); } + else + time_to_wait = INFINITE; + + w4[0] = signal_arrived; + w4[1] = input_available_event; while (len) { - size_t readlen = min ((unsigned) vmin, min (len, sizeof (buf))); - termios_printf ("reading %d bytes (vtime %d)", - min ((unsigned) vmin, min (len, sizeof (buf))), vtime); - - n = get_readahead_into_buffer (buf, readlen); - - if (!n && ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE) + rc = WaitForMultipleObjects (2, w4, FALSE, time_to_wait); + if (rc == WAIT_OBJECT_0) + { + /* if we've recieved signal after successfully reading some data, + just return all data successfully read */ + if (totalread > 0) + break; + set_sig_errno (EINTR); + return -1; + } + else if (rc == WAIT_FAILED) + { + termios_printf ("wait for input event failed, %E"); + break; + } + else if (rc == WAIT_TIMEOUT) + break; + rc = WaitForSingleObject (input_mutex, 1000); + if (rc == WAIT_FAILED) + { + termios_printf ("wait for input mutex failed, %E"); + break; + } + else if (rc == WAIT_TIMEOUT) + { + termios_printf ("failed to acquire input mutex after input event arrived"); + break; + } + if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, &bytes_in_pipe, NULL)) { - termios_printf ("read failed, %E"); - _raise (SIGHUP); + termios_printf ("PeekNamedPipe failed, %E"); + _raise (SIGHUP); + bytes_in_pipe = 0; } + readlen = min (bytes_in_pipe, min (len, sizeof (buf))); + if ( readlen ) + { + termios_printf ("reading %d bytes (vtime %d)", readlen, vtime); + if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE) + { + termios_printf ("read failed, %E"); + _raise (SIGHUP); + } + if (n) + { + len -= n; + totalread += n; + memcpy (ptr, buf, n); + ptr = (char *) ptr + n; + } + } + + if (readlen != bytes_in_pipe) + SetEvent (input_available_event); + + ReleaseMutex (input_mutex); if (get_ttyp ()->read_retval < 0) // read error { @@ -634,48 +707,28 @@ fhandler_tty_slave::read (void *ptr, size_t len) termios_printf ("saw EOF"); break; } - len -= n; - totalread += n; - memcpy (ptr, buf, n); - ptr = (char *) ptr + n; - if (get_ttyp ()->ti.c_lflag & ICANON) - break; - else if (totalread >= vmin) + if ( get_ttyp ()->ti.c_lflag & ICANON || + get_flags () & (O_NONBLOCK | O_NDELAY)) break; - - if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, &n, NULL)) - { - termios_printf("PeekNamedPipe failed, %E"); - break; - } - if (n == 0) - { - if (get_flags () & (O_NONBLOCK | O_NDELAY)) - break; - - /* We can't enter the blocking Readfile as signals will be lost. - * So, poll the pipe for data. - * FIXME: try to avoid polling... - * FIXME: Current EINTR scheme does not take vmin/vtime into account. - */ - if (!(get_ttyp ()->ti.c_lflag & ICANON)) - { - termios_printf("vmin %d vtime %d", vmin, vtime); - if (vmin == 0 && vtime == 0) - return 0; // min = 0, time = 0 - if (vtime == 0) - continue; // min > 0, time = 0 - while (vtime--) - { - PeekNamedPipe (get_handle (), NULL, 0, NULL, &n, NULL); - if (n) - break; - Sleep(10); - } - if (vtime == 0) - return totalread; - } - } + if (totalread >= vmin && (vmin > 0 || totalread > 0)) + break; + + /* vmin == 0 && vtime == 0: + * we've already read all input, if any, so return immediately + * vmin == 0 && vtime > 0: + * we've waited for input 10*vtime ms in WFSO(input_available_event), + * no matter whether any input arrived, we shouldn't wait any longer, + * so return immediately + * vmin > 0 && vtime == 0: + * here, totalread < vmin, so continue waiting until more data + * arrive + * vmin > 0 && vtime > 0: + * similar to the previous here, totalread < vmin, and timer + * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT, + * so "restart timer" and wait until more data arrive + */ + + if (vmin == 0) break; } termios_printf ("%d=read(%x, %d)", totalread, ptr, len); return totalread; @@ -721,18 +774,32 @@ fhandler_tty_common::dup (fhandler_base *child) errind = 3; goto err; } + if (!DuplicateHandle (hMainProc, input_available_event, hMainProc, + &fts->input_available_event, 0, 1, + DUPLICATE_SAME_ACCESS)) + { + errind = 4; + goto err; + } if (!DuplicateHandle (hMainProc, output_mutex, hMainProc, &fts->output_mutex, 0, 1, DUPLICATE_SAME_ACCESS)) { - errind = 4; + errind = 5; + goto err; + } + if (!DuplicateHandle (hMainProc, input_mutex, hMainProc, + &fts->input_mutex, 0, 1, + DUPLICATE_SAME_ACCESS)) + { + errind = 6; goto err; } if (!DuplicateHandle (hMainProc, get_handle (), hMainProc, &nh, 0, 1, DUPLICATE_SAME_ACCESS)) { - errind = 5; + errind = 7; goto err; } fts->set_io_handle (nh); @@ -741,7 +808,7 @@ fhandler_tty_common::dup (fhandler_base *child) &nh, 0, 1, DUPLICATE_SAME_ACCESS)) { - errind = 6; + errind = 8; goto err; } fts->set_output_handle (nh); @@ -752,7 +819,7 @@ fhandler_tty_common::dup (fhandler_base *child) &fts->inuse, 0, 1, DUPLICATE_SAME_ACCESS)) { - errind = 7; + errind = 9; goto err; } return 0; @@ -888,6 +955,10 @@ fhandler_tty_common::close () termios_printf ("CloseHandle (inuse), %E"); if (!ForceCloseHandle (output_mutex)) termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex); + if (!ForceCloseHandle (input_mutex)) + termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex); + if (!ForceCloseHandle (input_available_event)) + termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event); if (!ForceCloseHandle1 (get_handle (), from_pty)) termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ()); if (!ForceCloseHandle1 (get_output_handle (), to_pty)) @@ -1009,6 +1080,8 @@ fhandler_tty_common::set_close_on_exec (int val) if (inuse) set_inheritance (inuse, val); set_inheritance (output_mutex, val, "output_mutex"); + set_inheritance (input_mutex, val, "input_mutex"); + set_inheritance (input_available_event, val); set_inheritance (output_handle, val); } @@ -1027,6 +1100,13 @@ fhandler_tty_common::fixup_after_fork (HANDLE parent) fork_fixup (parent, output_mutex, "output_mutex"); ProtectHandle (output_mutex); } + if (input_mutex) + { + fork_fixup (parent, input_mutex, "input_mutex"); + ProtectHandle (input_mutex); + } + if (input_available_event) + fork_fixup (parent, input_available_event, "input_available_event"); fork_fixup (parent, output_handle, "output_handle"); fork_fixup (parent, inuse, "inuse"); } diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index baff0a4c2..070fa3e28 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -408,6 +408,9 @@ tty::common_init (fhandler_pty_master *ptym) return FALSE; } + if (!(ptym->input_available_event = get_event (INPUT_AVAILABLE_EVENT, FALSE))) + return FALSE; + char buf[40]; __small_sprintf (buf, OUTPUT_MUTEX, ntty); if (!(ptym->output_mutex = CreateMutex (&sec_all, FALSE, buf))) @@ -417,7 +420,16 @@ tty::common_init (fhandler_pty_master *ptym) return FALSE; } + __small_sprintf (buf, INPUT_MUTEX, ntty); + if (!(ptym->input_mutex = CreateMutex (&sec_all, FALSE, buf))) + { + termios_printf ("can't create %s", buf); + set_errno (ENOENT); + return FALSE; + } + ProtectHandle1 (ptym->output_mutex, output_mutex); + ProtectHandle1 (ptym->input_mutex, input_mutex); winsize.ws_col = 80; winsize.ws_row = 25; diff --git a/winsup/cygwin/tty.h b/winsup/cygwin/tty.h index bdd6eaedf..36f7ae19d 100644 --- a/winsup/cygwin/tty.h +++ b/winsup/cygwin/tty.h @@ -23,7 +23,9 @@ details. */ #define IOCTL_REQUEST_EVENT "cygtty%d.ioctl.request" #define IOCTL_DONE_EVENT "cygtty%d.ioctl.done" #define RESTART_OUTPUT_EVENT "cygtty%d.output.restart" +#define INPUT_AVAILABLE_EVENT "cygtty%d.input.avail" #define OUTPUT_MUTEX "cygtty%d.output.mutex" +#define INPUT_MUTEX "cygtty%d.input.mutex" #define TTY_SLAVE_ALIVE "cygtty%x.slave_alive" #define TTY_MASTER_ALIVE "cygtty%x.master_alive" @@ -111,6 +113,12 @@ public: __small_sprintf (buf, OUTPUT_MUTEX, ntty); return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf); } + HANDLE open_input_mutex (BOOL inherit = FALSE) + { + char buf[80]; + __small_sprintf (buf, INPUT_MUTEX, ntty); + return OpenMutex (MUTEX_ALL_ACCESS, inherit, buf); + } BOOL exists () { HANDLE h = open_output_mutex (); |