On 2020-03-12 16:08, Corinna Vinschen wrote:
On Mar 12 15:44, Corinna Vinschen wrote:
On Mar 12 15:20, Åke Rehnman via Cygwin wrote:
I think the problem is if the number of bytes requested are more than what
To clarify: number of bytes == VMIN?
no number of bytes requested from ReadFile(). As far as I know Win32 has no concept of VMIN.

is in the buffer it is going to overlap the read function (because of VTIME)
and immediately after that CancelIO is called. Contrary to what is mentioned
in the source code I think CancelIO is actually discarding data...
So far we didn't have that experience.  CancelIO is usually safe
in this regard.
The data is MIA somehow...

   /* Use CancelIo rather than PurgeComm (PURGE_RXABORT) since
          PurgeComm apparently discards in-flight bytes while CancelIo
          only stops the overlapped IO routine. */


My suggestion is the following patch:

diff --git a/winsup/cygwin/fhandler_serial.cc
b/winsup/cygwin/fhandler_serial.cc
index 69e5768f6..afa8871bf 100644
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -898,7 +898,11 @@ fhandler_serial::tcsetattr (int action, const struct
termios *t)
    {
      memset (&to, 0, sizeof (to));

-    if ((vmin_ > 0) && (vtime_ == 0))
+       if (is_nonblocking())
+       {
+               to.ReadIntervalTimeout = MAXDWORD;
+       }
+    else if ((vmin_ > 0) && (vtime_ == 0))
What if you switch to !O_NONBLOCK after calling tcsetattr?  The
setting of ReadIntervalTimeout would be lost then.

Either we have to repeat calling SetCommTimeouts every time
we switch mode, or we have to do the above setting temporary
every time we call ReadFile in non blocking mode.
True.
What about this:

diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc
--- a/winsup/cygwin/fhandler_serial.cc
+++ b/winsup/cygwin/fhandler_serial.cc
@@ -68,6 +68,16 @@ fhandler_serial::raw_read (void *ptr, size_t& ulen)
        goto err;
        else if (ev)
        termios_printf ("error detected %x", ev);
+      else if (is_nonblocking ())
+       {
+         if (!st.cbInQue)
+           {
+             tot = -1;
+             set_errno (EAGAIN);
+             goto out;
+           }
+         inq = st.cbInQue;
+       }
        else if (st.cbInQue && !vtime_)
        inq = st.cbInQue;
        else if (!is_nonblocking () && !overlapped_armed)

Looks promising. I will try it.

BTW there is a gremlin in the "else if (ev)" line....

/Ake

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to