On 17.12.15 21:22, Stefan Beller wrote:
> On Thu, Dec 17, 2015 at 12:12 PM, Torsten Bögershausen <[email protected]> wrote:
>> On 16.12.15 01:04, Stefan Beller wrote:
>>> The man page of read(2) says:
>>>
>>> EAGAIN The file descriptor fd refers to a file other than a socket
>>> and has been marked nonblocking (O_NONBLOCK), and the read
>>> would block.
>>>
>>> EAGAIN or EWOULDBLOCK
>>> The file descriptor fd refers to a socket and has been marked
>>> nonblocking (O_NONBLOCK), and the read would block. POSIX.1-2001
>>> allows either error to be returned for this case, and does not
>>> require these constants to have the same value, so a portable
>>> application should check for both possibilities.
>>>
>>> If we get an EAGAIN or EWOULDBLOCK the fd must have set O_NONBLOCK.
>>> As the intent of xread is to read as much as possible either until the
>>> fd is EOF or an actual error occurs, we can ease the feeder of the fd
>>> by not spinning the whole time, but rather wait for it politely by not
>>> busy waiting.
>>>
>>> We should not care if the call to poll failed, as we're in an infinite
>>> loop and can only get out with the correct read().
>> I'm not sure if this is valid under all circumstances:
>> This is what "man poll" says under Linux:
>> []
>> ENOMEM There was no space to allocate file descriptor tables.
>> []
>> And this is from Mac OS, ("BSD System Calls Manual")
>> ERRORS
>> Poll() will fail if:
>>
>> [EAGAIN] Allocation of internal data structures fails. A sub-
>> sequent request may succeed.
>> And this is opengroup:
>> http://pubs.opengroup.org/onlinepubs/9699919799//functions/poll.html:
>> [EAGAIN]
>> The allocation of internal data structures failed but a subsequent
>> request may succeed.
>>
>> read() may return EAGAIN, but poll() may fail to allocate memory, and fail.
>> Is it always guaranteed that the loop is terminated?
>
> In case poll fails (assume a no op for it), the logic should not have
> changed by this patch?
>
> Looking closely:
>
>>> while (1) {
>>> nr = read(fd, buf, len);
>>> - if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
>>> - continue;
>>> + if (nr < 0) {
>>> + if (errno == EINTR)
>>> + continue;
>>> + if (errno == EAGAIN || errno == EWOULDBLOCK) {
>>> + struct pollfd pfd;
>>> + pfd.events = POLLIN;
>>> + pfd.fd = fd;
>>> + /*
>>> + * it is OK if this poll() failed; we
>>> + * want to leave this infinite loop
>>> + * only when read() returns with
>>> + * success, or an expected failure,
>>> + * which would be checked by the next
>>> + * call to read(2).
>>> + */
>>> + poll(&pfd, 1, -1);
>
> Or do you mean to insert another continue in here?
I was thinking that we run into similar loop as before:
read() returns -1; errno = EAGAIN /* No data to read */
poll() returns -1; errno = EAGAIN /* poll failed. If the fd was OK, the failure
may be temporaly,
as much as poll() can see.
But most probably we run out ouf memory */
So the code would look like this:
if (!poll(&pfd, 1, -1))
return -1;
>
>>> + }
>>> + }
>>> return nr;
>>> }
>>> }
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html