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

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.

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

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.

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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.htmlIf we have an error event in ev it will make a blocking read even if
VTIME==0.