提交 ef1cf016 编写于 作者: E Eric Wong 提交者: Junio C Hamano

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: 1079c4be ("xread: poll on non blocking fds")
Signed-off-by: NEric Wong <e@80x24.org>
Reviewed-by: NJeff King <peff@peff.net>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 c22f6202
...@@ -271,8 +271,26 @@ ssize_t xwrite(int fd, const void *buf, size_t len) ...@@ -271,8 +271,26 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
len = MAX_IO_SIZE; len = MAX_IO_SIZE;
while (1) { while (1) {
nr = write(fd, buf, len); nr = write(fd, buf, len);
if ((nr < 0) && (errno == EAGAIN || errno == EINTR)) if (nr < 0) {
continue; 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; return nr;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册