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

Åke Rehnman ake.rehnman@gmail.com
Thu Mar 12 17:04:05 GMT 2020


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




More information about the Cygwin mailing list