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