diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2011-05-03 11:58:13 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2011-05-03 11:58:13 +0400 |
commit | 3ff46ba8532f76c879a68bd70b75dc0a30a9133b (patch) | |
tree | 0877e30bcb8695c0e3a58f46f00ca63d96294011 /winsup/cygwin/fhandler_tty.cc | |
parent | af4f7961d0688f932ab84166cdcc414e7ad3432d (diff) |
* fhandler_tty.cc (fhandler_tty_slave::read): Set WFMO timeout to 0 for
nonblocking case. Drop useless waiter variable. Rewrite wait for
input_available_event to use a switch statement. Handle timeout and
failure more gracefully. Make restartable and cancelable. Rewrite
wait for input_mutex to use WFMO and a switch statement. Handle
timeout and failure more gracefully. Make restartable and cancelable.
Diffstat (limited to 'winsup/cygwin/fhandler_tty.cc')
-rw-r--r-- | winsup/cygwin/fhandler_tty.cc | 111 |
1 files changed, 74 insertions, 37 deletions
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 5b0a1c595..6699cbe37 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -808,12 +808,10 @@ fhandler_tty_slave::read (void *ptr, size_t& len) char buf[INP_BUFFER_SIZE]; char peek_buf[INP_BUFFER_SIZE]; DWORD time_to_wait; - DWORD rc; - HANDLE w4[2]; termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ()); - if (!ptr) /* Indicating tcflush(). */ + if (is_nonblocking () || !ptr) /* Indicating tcflush(). */ time_to_wait = 0; else if ((get_ttyp ()->ti.c_lflag & ICANON)) time_to_wait = INFINITE; @@ -833,47 +831,88 @@ fhandler_tty_slave::read (void *ptr, size_t& len) time_to_wait = !vtime ? INFINITE : 100 * vtime; } - w4[0] = signal_arrived; - w4[1] = input_available_event; - - DWORD waiter = time_to_wait; while (len) { - rc = WaitForMultipleObjects (2, w4, FALSE, waiter); - - if (rc == WAIT_TIMEOUT) + HANDLE w4[3] = { input_available_event, signal_arrived, + pthread::get_cancel_event () }; + DWORD cnt = w4[2] ? 3 : 2; + switch (WaitForMultipleObjects (cnt, w4, FALSE, time_to_wait)) { - termios_printf ("wait timed out, waiter %u", waiter); + case WAIT_OBJECT_0: break; - } - - if (rc == WAIT_FAILED) - { + case WAIT_OBJECT_0 + 1: + if (totalread > 0) + goto out; + if (_my_tls.call_signal_handler ()) + continue; + termios_printf ("wait catched signal"); + set_sig_errno (EINTR); + totalread = -1; + goto out; + case WAIT_OBJECT_0 + 2: + pthread::static_cancel_self (); + /*NOTREACHED*/ + case WAIT_TIMEOUT: + termios_printf ("wait timed out, time_to_wait %u", time_to_wait); + if (!totalread) + { + set_sig_errno (EAGAIN); + totalread = -1; + } + goto out; + default: termios_printf ("wait for input event failed, %E"); - break; + if (!totalread) + { + __seterrno (); + totalread = -1; + } + goto out; } - - if (rc == WAIT_OBJECT_0) + /* Now that we know that input is available we have to grab the + input mutex. */ + w4[0] = input_mutex; + switch (WaitForMultipleObjects (cnt, w4, FALSE, 1000)) { - /* if we've received signal after successfully reading some data, - just return all data successfully read */ + case WAIT_OBJECT_0: + case WAIT_ABANDONED_0: + break; + case WAIT_OBJECT_0 + 1: if (totalread > 0) - break; + goto out; + if (_my_tls.call_signal_handler ()) + continue; + termios_printf ("wait for mutex catched signal"); set_sig_errno (EINTR); - len = (size_t) -1; - return; - } - - rc = WaitForSingleObject (input_mutex, 1000); - if (rc == WAIT_FAILED) - { + totalread = -1; + goto out; + case WAIT_OBJECT_0 + 2: + pthread::static_cancel_self (); + /*NOTREACHED*/ + case WAIT_TIMEOUT: + termios_printf ("failed to acquire input mutex after input event " + "arrived"); + /* If we have a timeout, we can simply handle this failure to + grab the mutex as an EAGAIN situation. Otherwise, if this + is an infinitely blocking read, restart the loop. */ + if (time_to_wait != INFINITE) + { + if (!totalread) + { + set_sig_errno (EAGAIN); + totalread = -1; + } + goto out; + } + continue; + default: 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 (!totalread) + { + __seterrno (); + totalread = -1; + } + goto out; } if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL)) { @@ -974,10 +1013,8 @@ fhandler_tty_slave::read (void *ptr, size_t& len) if (vmin == 0) break; - - if (n) - waiter = time_to_wait; } +out: termios_printf ("%d=read(%x, %d)", totalread, ptr, len); len = (size_t) totalread; } |