Another pipe-related problem?

Ken Brown kbrown@cornell.edu
Wed Nov 10 02:02:35 GMT 2021


On 11/9/2021 7:37 PM, Takashi Yano via Cygwin wrote:
> On Wed, 10 Nov 2021 09:16:13 +0900
> Takashi Yano wrote:
>> On Wed, 10 Nov 2021 08:48:22 +0900
>> Takashi Yano wrote:
>>> On Wed, 10 Nov 2021 08:29:32 +0900
>>> Takashi Yano wrote:
>>>> On Wed, 10 Nov 2021 08:22:45 +0900
>>>> Takashi Yano wrote:
>>>>> On Tue, 9 Nov 2021 09:11:28 -0500
>>>>> Ken Brown wrote:
>>>>>> I'll have to reproduce the hang myself in order to test this (or maybe you could
>>>>>> test it), but I now have a new guess: If the read call above keeps failing with
>>>>>> EINTR, then we're in an infinite loop.  This could happen because of the
>>>>>> following code in fhandler_pipe::raw_read:
>>>>>>
>>>>>>     DWORD waitret = cygwait (read_mtx, timeout);
>>>>>>     switch (waitret)
>>>>>>       {
>>>>>>       case WAIT_OBJECT_0:
>>>>>>         break;
>>>>>>       case WAIT_TIMEOUT:
>>>>>>         set_errno (EAGAIN);
>>>>>>         len = (size_t) -1;
>>>>>>         return;
>>>>>>       default:
>>>>>>         set_errno (EINTR);
>>>>>>         len = (size_t) -1;
>>>>>>         return;
>>>>>>       }
>>>>>>
>>>>>> Takashi, is EINTR really the appropriate errno in the default case?  Isn't
>>>>>> cygwait supposed to handle signals?
>>>>>
>>>>> I assume cygwait() returns WAIT_SIGNALED when signalled
>>>>> by SIGINT, SIGTERM, SIGTSTP, etc...  In this case, EINTR
>>>>> should return I think.
>>>>>
>>>>> Is it wrong?
>>>>
>>>> Ah, if SA_RESTART is set, we should continue to read even
>>>> if signalled...
> [...]
>> No, we don't have to do that because cygwait() do the same
>> internally. cygwain() returns WAIT_SIGNALED when signalled
>> only if SA_RESTART is not set. So, the current code LGTM.
> 
> Ah, however, should we handle WAIT_CANCELED here and call
> pthread::static_cancel_self() as following?
> 
>     DWORD waitret = cygwait (read_mtx, timeout);
>     switch (waitret)
>       {
>       case WAIT_OBJECT_0:
>         break;
>       case WAIT_TIMEOUT:
>         set_errno (EAGAIN);
>         len = (size_t) -1;
>         return;
>       WAIT_SIGNALED:
>         set_errno (EINTR);
>         len = (size_t) -1;
>         return;
>       WAIT_CANCELED:
>         pthread::static_cancel_self ();
>         /* NOTREACHED */
>       default:
>         /* Should not reach here. */
>         __seterrno ();
>         len = (slze_t) -1;
>         return;
>       }

This looks better to me.  I think the default case actually could be reached if 
WFMO returns WAIT_FAILED (admittedly unlikely).

Ken


More information about the Cygwin mailing list