Setting termios VMIN > 0 and VTIME > 0 on non blocking file

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
Hello all,

opening a file (serial port) with O_NONBLOCK and subsequently setting
termios VMIN and VTIME > 0 makes read() never ever return any data
(returns EAGAIN indefinitely).

Don't ask my why one would want to do something like this but apparently
the "screen" program think this is a good way of doing things...

Nevertheless not returning any data ever seems wrong.

Any insight on how it is supposed to work is welcome.

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Brian Inglis
On 2020-03-11 14:48, Åke Rehnman via Cygwin wrote:
> opening a file (serial port) with O_NONBLOCK and subsequently setting termios
> VMIN and VTIME > 0 makes read() never ever return any data (returns EAGAIN
> indefinitely).
> Don't ask my why one would want to do something like this but apparently the
> "screen" program think this is a good way of doing things...
> Nevertheless not returning any data ever seems wrong.
> Any insight on how it is supposed to work is welcome.

VMIN > 0 || VTIME > 0 implies blocking; O_NONBLOCK implies SIGIO delivery; see:

        https://www.tldp.org/HOWTO/pdf/Serial-Programming-HOWTO.pdf
        https://www.cmrr.umn.edu/~strupp/serial.html
        https://en.wikibooks.org/wiki/Serial_Programming/termios

also read the man pages carefully and *assume* nothing; functions should work
*exactly* as documented: there be dragons!

You have to set up for, or adapt to, the expected input speed and quantity, the
interrupt response overhead (hardware, OS, and C signal), and what else you want
to be able to do at the same time.

--
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada

This email may be disturbing to some readers as it contains
too much technical detail. Reader discretion is advised.
--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Norton Allen
On 3/11/2020 5:55 PM, Brian Inglis wrote:
> VMIN > 0 || VTIME > 0 implies blocking; O_NONBLOCK implies SIGIO delivery; see:

While I agree with everything else you said there, I don't believe
either of these are true, unless by 'implies' you mean that's how you
usually do it. I have done a lot of work with non-zero VMIN and/or VTIME
in non-blocking situations, and I've done non-blocking with different
approaches to delivery.

--
=============================================================
Norton Allen (he/him/his)
Software Engineer
Harvard University School of Engineering and Applied Sciences
12 Oxford St., Link Bldg. (Office 282)
Cambridge, MA  02138
Phone: (617) 998-5553
=============================================================

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
In reply to this post by Brian Inglis

On 2020-03-11 22:55, Brian Inglis wrote:
> VMIN > 0 || VTIME > 0 implies blocking; O_NONBLOCK implies SIGIO
> delivery; see:
> https://www.tldp.org/HOWTO/pdf/Serial-Programming-HOWTO.pdf
> https://www.cmrr.umn.edu/~strupp/serial.html
> https://en.wikibooks.org/wiki/Serial_Programming/termios
>
> also read the man pages carefully and *assume* nothing; functions should work
> *exactly* as documented: there be dragons!
>
According to https://www.cmrr.umn.edu/~strupp/serial.html "*Timeouts are
ignored in canonical input mode or when the/NDELAY/option is set on the
file via/open/or/fcntl/."*

This leads me to believe the current cygwin implementation is not
correct. Changing the VMIN and VTIME should have no effect on the read()
behavior if the file was opened with O_NOBLOCK.
**

*
*

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Norton Allen

On 3/11/2020 9:04 PM, Åke Rehnman via Cygwin wrote:

>
> On 2020-03-11 22:55, Brian Inglis wrote:
>> VMIN > 0 || VTIME > 0 implies blocking; O_NONBLOCK implies SIGIO
>> delivery; see:
>>     https://www.tldp.org/HOWTO/pdf/Serial-Programming-HOWTO.pdf
>>     https://www.cmrr.umn.edu/~strupp/serial.html
>>     https://en.wikibooks.org/wiki/Serial_Programming/termios
>>
>> also read the man pages carefully and *assume* nothing; functions
>> should work
>> *exactly* as documented: there be dragons!
>>
> According to https://www.cmrr.umn.edu/~strupp/serial.html "*Timeouts
> are ignored in canonical input mode or when the/NDELAY/option is set
> on the file via/open/or/fcntl/."*
>
> This leads me to believe the current cygwin implementation is not
> correct. Changing the VMIN and VTIME should have no effect on the
> read() behavior if the file was opened with O_NOBLOCK.
> **


Correct me if I am wrong, but O_NDELAY is not the same as O_NONBLOCK

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
On 2020-03-12 02:08, Norton Allen wrote:
> Correct me if I am wrong, but O_NDELAY is not the same as O_NONBLOCK

At least for cygwin those two are exactly the same... I think...

#define _FNONBLOCK      0x4000  /* non blocking I/O (POSIX style) */
#define _FNDELAY        _FNONBLOCK      /* non blocking I/O (4.2 style) */



--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Thomas Dickey-2
In reply to this post by Cygwin list mailing list
----- Original Message -----
| From: "Åke Rehnman" <[hidden email]>
| To: "cygwin" <[hidden email]>
| Sent: Wednesday, March 11, 2020 4:48:05 PM
| Subject: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

| Hello all,
|
| opening a file (serial port) with O_NONBLOCK and subsequently setting
| termios VMIN and VTIME > 0 makes read() never ever return any data
| (returns EAGAIN indefinitely).
|
| Don't ask my why one would want to do something like this but apparently
| the "screen" program think this is a good way of doing things...
|
| Nevertheless not returning any data ever seems wrong.
|
| Any insight on how it is supposed to work is welcome.

If not "correct", it's certainly inconsistent with all other systems.
I noticed it recently:

https://invisible-island.net/ncurses/tack/CHANGES.html#t20200220

https://github.com/cygwinports/tack/issues/1

It's either recently-broken, or just coincidence :-)

--
Thomas E. Dickey <[hidden email]>
http://invisible-island.net
ftp://ftp.invisible-island.net
--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list

On 2020-03-12 09:05, Thomas Dickey wrote:
> If not "correct", it's certainly inconsistent with all other systems.
> I noticed it recently:
>
> https://invisible-island.net/ncurses/tack/CHANGES.html#t20200220
>
> https://github.com/cygwinports/tack/issues/1
>
> It's either recently-broken, or just coincidence :-)


Beer fine for you Thomas for copying email-addresses in the reply :-)

Looking at Linux tty line discipline reveals the VMIN and VTIME are
ignored if O_NONBLOCK flag is set.

         if (!input_available_p(tty, 0)) {
             up_read(&tty->termios_rwsem);
             tty_buffer_flush_work(tty->port);
             down_read(&tty->termios_rwsem);
             if (!input_available_p(tty, 0)) {
                 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
                     retval = -EIO;
                     break;
                 }
                 if (tty_hung_up_p(file))
                     break;
                 /*
                  * Abort readers for ttys which never actually
                  * get hung up.  See __tty_hangup().
                  */
                 if (test_bit(TTY_HUPPING, &tty->flags))
                     break;
                 if (!timeout)
                     break; *<= EXIT HERE if VTIME == 0*
                 if (file->f_flags & O_NONBLOCK) {
                     retval = -EAGAIN; *<==== EXIT HERE*
                     break;
                 }
                 if (signal_pending(current)) {
                     retval = -ERESTARTSYS;
                     break;
                 }
                 up_read(&tty->termios_rwsem);

                 timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, *<===
BLOCKING HERE!*
                         timeout);

                 down_read(&tty->termios_rwsem);
                 continue;
             }
         }

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
In reply to this post by Cygwin list mailing list
Hi Åke,

On Mar 11 21:48, Åke Rehnman via Cygwin wrote:

> Hello all,
>
> opening a file (serial port) with O_NONBLOCK and subsequently setting
> termios VMIN and VTIME > 0 makes read() never ever return any data (returns
> EAGAIN indefinitely).
>
> Don't ask my why one would want to do something like this but apparently the
> "screen" program think this is a good way of doing things...
>
> Nevertheless not returning any data ever seems wrong.
>
> Any insight on how it is supposed to work is welcome.
[Please note that I can't test this myself, so we may need a bit of
 back and forth over this issue]

For a start, can you please strace the problem with a simple
testcase,like this:

  $ strace -o serio.trace <yourtestcase>

and send the source of your testcase as well as the serio.trace file
here?  It may show at which point the error code is generated.

I inspected the serial I/O read function and I only see a subtil
difference in terms of VMIN/VTIME which doesn't seem to be the culprit
at first glance.  In O_NONBLOCK mode, the underlying Windows function
ReadFile is called unconditionally.  My current hunch is this:

- If VMIN>0 && VTIME>0, the Windows equivalent of tcsetattr is
  told that VMIN>0.

- So, assuming VMIN == 2 in Windows.  If VTIME > 0, the Cygwin read
  function sets the number of bytes_to_read to 1 (this is old code,
  don't ask why).

- My assumption now is that the ReadFile function fails because it's
  supposed to return only 1 char, but VMIN is > 1.

There are two issues here.

- If my assumption is correct, the tcsetattr function must not
  set the Windows VMIN equivalent to != 0 in the O_NONBLOCK case.

- Also, as mention above, if VTIME > 0, Cygwin's read sets the number of
  bytes_to_read to 1.   Weirdly, it does so even if there are more than
  1 byte in the inbound queue.  This sounds wrong to me.

Ok, that's for a start, let's see if we can fix this behaviour.


Thanks,
Corinna
 
--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list

On 2020-03-12 12:40, Corinna Vinschen wrote:
>
> For a start, can you please strace the problem with a simple
> testcase,like this:
>
>    $ strace -o serio.trace <yourtestcase>
>
> and send the source of your testcase as well as the serio.trace file
> here?  It may show at which point the error code is generated.

Should I post those files to the mailing list? I tried emailing them to
you directly but it bounced...

--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
On Mar 12 14:32, Åke Rehnman via Cygwin wrote:

>
> On 2020-03-12 12:40, Corinna Vinschen wrote:
> >
> > For a start, can you please strace the problem with a simple
> > testcase,like this:
> >
> >    $ strace -o serio.trace <yourtestcase>
> >
> > and send the source of your testcase as well as the serio.trace file
> > here?  It may show at which point the error code is generated.
>
> Should I post those files to the mailing list? I tried emailing them to you
> directly but it bounced...
Mailing list, please.


Corinna

--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
In reply to this post by Corinna Vinschen-2

On 2020-03-12 12:40, Corinna Vinschen wrote:

>
> I inspected the serial I/O read function and I only see a subtil
> difference in terms of VMIN/VTIME which doesn't seem to be the culprit
> at first glance.  In O_NONBLOCK mode, the underlying Windows function
> ReadFile is called unconditionally.  My current hunch is this:
>
> - If VMIN>0 && VTIME>0, the Windows equivalent of tcsetattr is
>    told that VMIN>0.
>
> - So, assuming VMIN == 2 in Windows.  If VTIME > 0, the Cygwin read
>    function sets the number of bytes_to_read to 1 (this is old code,
>    don't ask why).
Do you have a pointer to this? I can not find it...

>
> - My assumption now is that the ReadFile function fails because it's
>    supposed to return only 1 char, but VMIN is > 1.
>
> There are two issues here.
>
> - If my assumption is correct, the tcsetattr function must not
>    set the Windows VMIN equivalent to != 0 in the O_NONBLOCK case.
>
> - Also, as mention above, if VTIME > 0, Cygwin's read sets the number of
>    bytes_to_read to 1.   Weirdly, it does so even if there are more than
>    1 byte in the inbound queue.  This sounds wrong to me.
>
I think the problem is if the number of bytes requested are more than
what 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...

   /* 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))
        {
         /* Returns immediately with whatever is in buffer on a ReadFile();
            or blocks if nothing found.  We will keep calling
ReadFile(); until


--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
On Mar 12 15:20, Åke Rehnman via Cygwin wrote:

>
> On 2020-03-12 12:40, Corinna Vinschen wrote:
> >
> > I inspected the serial I/O read function and I only see a subtil
> > difference in terms of VMIN/VTIME which doesn't seem to be the culprit
> > at first glance.  In O_NONBLOCK mode, the underlying Windows function
> > ReadFile is called unconditionally.  My current hunch is this:
> >
> > - If VMIN>0 && VTIME>0, the Windows equivalent of tcsetattr is
> >    told that VMIN>0.
> >
> > - So, assuming VMIN == 2 in Windows.  If VTIME > 0, the Cygwin read
> >    function sets the number of bytes_to_read to 1 (this is old code,
> >    don't ask why).
> Do you have a pointer to this? I can not find it...
That's because it's not true.  I created this mail during lunch break
and screwed up.

> > - My assumption now is that the ReadFile function fails because it's
> >    supposed to return only 1 char, but VMIN is > 1.
> >
> > There are two issues here.
> >
> > - If my assumption is correct, the tcsetattr function must not
> >    set the Windows VMIN equivalent to != 0 in the O_NONBLOCK case.
> >
> > - Also, as mention above, if VTIME > 0, Cygwin's read sets the number of
> >    bytes_to_read to 1.   Weirdly, it does so even if there are more than
> >    1 byte in the inbound queue.  This sounds wrong to me.
> >
> I think the problem is if the number of bytes requested are more than what
To clarify: number of bytes == 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.

>   /* 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.


Corinna

--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
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?
>
> > 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.
>
> >   /* 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.
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)


Corinna

--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
In reply to this post by Corinna Vinschen-2

On 2020-03-12 15:13, Corinna Vinschen wrote:

> On Mar 12 14:32, Åke Rehnman via Cygwin wrote:
>> On 2020-03-12 12:40, Corinna Vinschen wrote:
>>> For a start, can you please strace the problem with a simple
>>> testcase,like this:
>>>
>>>     $ strace -o serio.trace <yourtestcase>
>>>
>>> and send the source of your testcase as well as the serio.trace file
>>> here?  It may show at which point the error code is generated.
>> Should I post those files to the mailing list? I tried emailing them to you
>> directly but it bounced...
> Mailing list, please.

--
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

test2.c (1K) Download Attachment
test2.txt (889 bytes) Download Attachment
log2.txt (69K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list
In reply to this post by Corinna Vinschen-2

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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

ASSI
In reply to this post by Thomas Dickey-2
Thomas Dickey writes:
> It's either recently-broken, or just coincidence :-)

I've looke and it's been introduced into newlib around four years ago,
so I'd tend to favor the coincidence camp.  :-)


Regards,
Achim.
--
+<[Q+ Matrix-12 WAVE#46+305 Neuron microQkb Andromeda XTk Blofeld]>+

SD adaptation for Waldorf microQ V2.22R2:
http://Synth.Stromeko.net/Downloads.html#WaldorfSDada
--
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 | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
In reply to this post by Cygwin list mailing list
On Mar 12 17:42, Åke Rehnman via Cygwin wrote:

>
> On 2020-03-12 15:13, Corinna Vinschen wrote:
> > On Mar 12 14:32, Åke Rehnman via Cygwin wrote:
> > > On 2020-03-12 12:40, Corinna Vinschen wrote:
> > > > For a start, can you please strace the problem with a simple
> > > > testcase,like this:
> > > >
> > > >     $ strace -o serio.trace <yourtestcase>
> > > >
> > > > and send the source of your testcase as well as the serio.trace file
> > > > here?  It may show at which point the error code is generated.
> > > Should I post those files to the mailing list? I tried emailing them to you
> > > directly but it bounced...
> > Mailing list, please.
>

> #include <stdio.h>
> #include <error.h>
> #include <errno.h>
> #include <sys/select.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <termios.h>
> #include <sys/ioctl.h>
> [...]

Thanks!  So that's what we're up against here :)


Corinna

--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Corinna Vinschen-2
In reply to this post by Cygwin list mailing list
On Mar 12 18:04, Åke Rehnman via Cygwin wrote:
>
> 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.

Right, just this weird TimeoutMultiplier, but nevertheless I wasn't sure
what you meant.

> > > > 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...

Yes, but we're calling CancelIo in other circumstances in Cygwin and
there were no reports of missing data.  CancelIo is just supposed to
terminate the currently running overlapped IO, not to discard any
in-flight data.  If that's different for serial IO, there would be no
way to terminate serial overlapped IO gracefully.  Well, yeah, it's
Windows, but still...

> > > > -    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....
A gremlin?  Would you mind to explain?  Btw., if you find a bug
in the code, we do take patches :) https://cygwin.com/contrib.html


Thanks,
Corinna

--
Corinna Vinschen
Cygwin Maintainer

--
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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Setting termios VMIN > 0 and VTIME > 0 on non blocking file

Cygwin list mailing list

On 2020-03-13 11:12, Corinna Vinschen wrote:

> On Mar 12 18:04, Åke Rehnman via Cygwin wrote:
>> 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.
> Right, just this weird TimeoutMultiplier, but nevertheless I wasn't sure
> what you meant.
>
>>>>> 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...
> Yes, but we're calling CancelIo in other circumstances in Cygwin and
> there were no reports of missing data.  CancelIo is just supposed to
> terminate the currently running overlapped IO, not to discard any
> in-flight data.  If that's different for serial IO, there would be no
> way to terminate serial overlapped IO gracefully.  Well, yeah, it's
> Windows, but still...
I have scrutinized the microsoft serial driver reference implementation
(https://github.com/microsoft/Windows-driver-samples/blob/master/serial/serial/read.c)
and it looks to me as CancelIo does not purge any data. However since
the driver is vendor dependent in my case FTDI it is impossible to know
exactly what is going on since it is closed source.

>>>>> -    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.
Your patch works (for my test case and screen). Question is if we have
to consider the case where ulen==0 ...
>>
>> BTW there is a gremlin in the "else if (ev)" line....
> A gremlin?  Would you mind to explain?  Btw., if you find a bug
> in the code, we do take patches :) https://cygwin.com/contrib.html
If we have an error event in ev it will make a blocking read even if
VTIME==0.

--
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
12