xwrite: poll on non-blocking FDs
write(2) can hit the same EAGAIN/EWOULDBLOCK errors as read(2),
so busy-looping on a non-blocking FD is a waste of resources.
Currently, I do not know of a way for this happen:
* the NonBlocking directive in systemd does not apply to stdin,
stdout, or stderr.
* xinetd provides no way to set the non-blocking flag at all
But theoretically, it's possible a careless C10K HTTP server
could use pipe2(..., O_NONBLOCK) to setup a pipe for
git-http-backend with only the intent to use non-blocking reads;
but accidentally leave non-blocking set on the write end passed
as stdout to git-upload-pack.
Followup-to: 1079c4be0b
("xread: poll on non blocking fds")
Signed-off-by: Eric Wong <e@80x24.org>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
c22f620205
commit
ef1cf0167a
22
wrapper.c
22
wrapper.c
@ -271,8 +271,26 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
|
||||
len = MAX_IO_SIZE;
|
||||
while (1) {
|
||||
nr = write(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 = POLLOUT;
|
||||
pfd.fd = fd;
|
||||
/*
|
||||
* it is OK if this poll() failed; we
|
||||
* want to leave this infinite loop
|
||||
* only when write() returns with
|
||||
* success, or an expected failure,
|
||||
* which would be checked by the next
|
||||
* call to write(2).
|
||||
*/
|
||||
poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user