diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index da85ec122..d0f613d21 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,8 @@ +2012-05-25 Corinna Vinschen + + * fhandler_serial.cc (fhandler_serial::raw_read): Just call ReadFile + directly in case of non-blocking I/O and handle result gracefully. + 2012-05-24 Corinna Vinschen * thread.cc (__cygwin_lock_lock): Replace null thread check with test diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc index 677b6221f..c58d0418c 100644 --- a/winsup/cygwin/fhandler_serial.cc +++ b/winsup/cygwin/fhandler_serial.cc @@ -71,7 +71,7 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen) termios_printf ("error detected %x", ev); else if (st.cbInQue && !vtime_) inq = st.cbInQue; - else if (!overlapped_armed) + else if (!is_nonblocking () && !overlapped_armed) { if ((size_t) tot >= minchars) break; @@ -83,16 +83,6 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen) } else if (GetLastError () != ERROR_IO_PENDING) goto err; - else if (is_nonblocking ()) - { - PurgeComm (get_handle (), PURGE_RXABORT); - if (tot == 0) - { - tot = -1; - set_errno (EAGAIN); - } - goto out; - } else { overlapped_armed = 1; @@ -132,7 +122,14 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen) goto err; else if (is_nonblocking ()) { - PurgeComm (get_handle (), PURGE_RXABORT); + /* Use CancelIo rather than PurgeComm (PURGE_RXABORT) since + PurgeComm apparently discards in-flight bytes while CancelIo + only stops the overlapped IO routine. */ + CancelIo (get_handle ()); + if (GetOverlappedResult (get_handle (), &io_status, &n, FALSE)) + tot = n; + else if (GetLastError () != ERROR_IO_INCOMPLETE) + goto err; if (tot == 0) { tot = -1;