git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCHv3 02/13] xread: poll on non blocking fds

From
Stefan Beller <sbeller@google.com>
Date
Sep 23, 2015, 00:14 UTC
Message-ID
<CAGZ79kYKxNAXhbmXEtMeBYeGqu8i4bcUW_hpjLaPSF4p5O=uBg@mail.gmail.com>
In-Reply-To
<xmqqlhby2pj0.fsf@gitster.mtv.corp.google.com>
On Tue, Sep 22, 2015 at 1:00 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 27 quoted lines
> Jeff King <peff@peff.net> writes:
>
>> On Tue, Sep 22, 2015 at 12:45:51PM -0700, Junio C Hamano wrote:
>>
>>> One caveat is that the caller may not know in the first place.
>>>
>>> The last time I checked the existing callers of xread(), there were
>>> a few that read from a file descriptor they did not open themselves
>>> (e.g. unpack-objects that read from standard input).  The invoker of
>>> these processes is free to do O_NONBLOCK their input stream for
>>> whatever reason.
>>
>> Yeah. I do not think this is a bug at all; the user might have their
>> reasons for handing off an O_NONBLOCK pipe. If we take xread() to mean
>> "try to read from fd until we get a real error, some data, or an EOF",
>> then it is perfectly reasonable to replace spinning on read() (which we
>> do now) with a poll() for efficiency. The caller (and the user) does not
>> have to care, and should not notice; the outcome will be the same.
>
> I think we are in agreement, and that answers the question/guidance
> Stefan asked earlier in $gmane/278414, which was:
>
>> So rather a combination of both, with the warning only spewing every
>> 5 seconds or such?
>
> and the answer obviously is "No warning, do a poll() without timeout
> to block".
Ok. Expect that in a reroll.
To answer the first question upthread:
> I can sort of see EINTR but why is ENOMEM any special than other errors?

So we have 4 kinds of additional errors, when adding the poll. When we want to keep the behavior as close to the original as possible, we should not error out for things we had under control previously.

       EFAULT The array given as argument was not contained in the
calling program's address space.
       EINTR  A signal occurred before any requested event; see signal(7).
       EINVAL The nfds value exceeds the RLIMIT_NOFILE value.
       ENOMEM There was no space to allocate file descriptor tables.

I don't see a way EFAULT can be returned as we have the array hard coded on the stack. (No tricks with the heap or anything, we'll have it on the stack)

EINTR is possible while waiting. Actually it doesn't matter if we retry the poll or read first and then poll again, so we can easily just continue and do the read.

EINVAL is highly unlikely (as nfds == 1 in the case here), but can happen. ENOMEM is similar to EINVAL.

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(..). So maybe an implementation like this would already suffice:

ssize_t xread(int fd, void *buf, size_t len)
{
    ssize_t nr;
    if (len > MAX_IO_SIZE)
        len = MAX_IO_SIZE;
    while (1) {
        nr = read(fd, buf, len);
        if (nr < 0) {
            if (errno == EINTR)
                continue;
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                struct pollfd pfd;
                pfd.events = POLLIN;
                pfd.fd = fd;
                /* We deliberately ignore the return value of poll. */
                poll(&pfd, 1, -1);
                continue;
            }
        }
        return nr;
    }
}

In the resend I'll only check for EINTR and in other cases of early poll failure, we just die(..).

Previous: Junio C HamanoNext: Junio C Hamano
Message 12 of 48 in “[PATCHv3 00/13] fetch submodules in parallel and a preview on parallel "submodule update"”
  1. Stefan BellerSep 21, 2015
  2. 01/13 Sending "Fetching submodule <foo>" output to stderrStefan Beller, Sep 21, 2015
  3. Junio C HamanoSep 21, 2015
  4. 02/13 xread: poll on non blocking fdsStefan Beller, Sep 21, 2015
  5. Junio C HamanoSep 21, 2015
  6. Torsten BögershausenSep 22, 2015
  7. Jacob KellerSep 22, 2015
  8. Torsten BögershausenSep 22, 2015
  9. Junio C HamanoSep 22, 2015
  10. Jeff KingSep 22, 2015
  11. Junio C HamanoSep 22, 2015
  12. Stefan BellerSep 23, 2015
  13. Junio C HamanoSep 23, 2015
  14. Jeff KingSep 23, 2015
  15. Eric SunshineSep 21, 2015
  16. Junio C HamanoSep 22, 2015
  17. Stefan BellerSep 22, 2015
  18. Junio C HamanoSep 22, 2015
  19. Stefan BellerSep 22, 2015
  20. 03/13 xread_nonblock: add functionality to read from fds nonblockinglyStefan Beller, Sep 21, 2015
  21. Junio C HamanoSep 22, 2015
  22. Junio C HamanoSep 22, 2015
  23. Jacob KellerSep 22, 2015
  24. Jacob KellerSep 22, 2015
  25. Junio C HamanoSep 22, 2015
  26. 04/13 strbuf: add strbuf_read_once to read without blockingStefan Beller, Sep 21, 2015
  27. Junio C HamanoSep 22, 2015
  28. Jacob KellerSep 22, 2015
  29. 05/13 run-command: factor out return value computationStefan Beller, Sep 21, 2015
  30. Junio C HamanoSep 22, 2015
  31. 06/13 run-command: add an asynchronous parallel child processorStefan Beller, Sep 21, 2015
  32. Junio C HamanoSep 22, 2015
  33. Stefan BellerSep 22, 2015
  34. Junio C HamanoSep 22, 2015
  35. Stefan BellerSep 22, 2015
  36. Junio C HamanoSep 22, 2015
  37. Stefan BellerSep 22, 2015
  38. Junio C HamanoSep 22, 2015
  39. 07/13 fetch_populated_submodules: use new parallel job processingStefan Beller, Sep 21, 2015
  40. Junio C HamanoSep 22, 2015
  41. 08/13 submodules: allow parallel fetching, add tests and documentationStefan Beller, Sep 21, 2015
  42. 09/13 submodule config: keep update strategy aroundStefan Beller, Sep 21, 2015
  43. Eric SunshineSep 22, 2015
  44. Stefan BellerSep 22, 2015
  45. 10/13 git submodule update: cmd_update_recursiveStefan Beller, Sep 21, 2015
  46. 11/13 git submodule update: cmd_update_cloneStefan Beller, Sep 21, 2015
  47. 12/13 git submodule update: cmd_update_fetchStefan Beller, Sep 21, 2015
  48. 13/13 Rewrite submodule update in CStefan Beller, Sep 21, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.