On Thu, Sep 17, 2015 at 10:54:39AM -0700, Junio C Hamano wrote:
> OK. Trying to repurpose strbuf_read() for non-blocking FD was a
> silly idea to begin with, as it wants to read thru to the EOF, and
> setting FD explicitly to O_NONBLOCK is a sign that the caller wants
> to grab as much as possible and does not want to wait for the EOF.
>
> So assuming we want strbuf_read_nonblock(), what interface do we
> want from it? We could:
>
> * Have it grab as much as possible into sb as long as it does not
> block?
>
> * Have it grab reasonably large amount into sb, and not blocking is
> an absolute requirement, but the function is not required to read
> everything that is available on the FD (i.e. the caller is
> expected to loop)?
I think we are crossing emails, but I would definitely argue for the
latter.
> If we choose the latter, then your "EAGAIN? EOF?" becomes easier,
> no? We only have to do a single call to xread(), and then we:
>
> - get EAGAIN or EWOULDBLOCK; leave sb as-is, set errno==EAGAIN and
> return -1.
>
> - get something (in which case that is not an EOF yet); append to
> sb, return the number of bytes.
>
> - get EOF; leave sb as-is, return 0.
Yes, exactly.
> ssize_t strbuf_read_nonblock(struct strbuf *sb, int fd, size_t hint)
> {
> strbuf_grow(sb, hint ? hint : 8192);
> ssize_t want = sb->alloc - sb->len - 1;
> ssize_t got = xread_nonblock(fd, sb->buf + sb->len, want);
> if (got < 0) {
> if (errno == EWOULDBLOCK)
> errno = EAGAIN; /* make life easier for the caller */
> return got;
> }
I like the normalizing of errno, but that should probably be part of
xread_nonblock(), I would think.
> sb->len += got;
> sb->buf[sb->len] = '\0';
Use strbuf_setlen() here?
> return got;
If "got == 0", we naturally do not change sb->len at all, and the strbuf
is left unchanged. But do we want to de-allocate what we allocated in
strbuf_grow() above? That is what strbuf_read() does, but I think it is
even less likely to help anybody here. With the original strbuf_read(),
you might do:
if (strbuf_read(&buf, fd, hint) <= 0)
return; /* got nothing */
but because the nature of strbuf_read_nonblock() is to call it from a
loop, you'd want to strbuf_release() when you leave the loop anyway.
-Peff
--
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