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

Re: [PATCH 1/2] xread: retry after poll on EAGAIN/EWOULDBLOCK

From
EWEric Wong <e@80x24.org>
Date
Jun 27, 2016, 20:13 UTC
Message-ID
<20160627201311.GA7039@dcvr.yhbt.net>
In-Reply-To
<CAGZ79kZ94PaOfq3GimWiHULbTE7ihMzL9S=Y+npQ4F5gGwFrsA@mail.gmail.com>
Stefan Beller <sbeller@google.com> wrote:
Show 7 quoted lines
> On Mon, Jun 27, 2016 at 7:36 AM, Jeff King <peff@peff.net> wrote:
> > It's also true that our error rate will never be 0%. So some bugs will
> > always slip through, some review comments will be forgotten, etc. Eric
> > did find and fix the bug just now, so the "many eyes" theory did work
> > here eventually.
> 
> Eric, thanks for catching and fixing the bug!

No problem :) I only noticed it because I was scanning emails randomly and Duy and David's index-helper thread turned up.

> Quite a while ago, when I started doing code reviews professionally, I wondered
> if the code review procedure can be semi-automated, as automation helps keeping
> the error rate low. By that I mean having a check list which I can
> check off each point

Maybe a test case or even a small unit test would've helped. I didn't notice the problem in xread until:

1) I copied the code into xwrite
2) s/POLLIN/POLLOUT/;
3) forced EAGAIN using a patched, home-baked HTTP server

The biggish comment before the poll() obscured the missing "continue" for me. I read xread() before and did not notice the missing "continue".

Maybe the following optional patch on top of this series improves readability:

----------8<--------
Subject: [PATCH 3/2] hoist out io_wait function for xread and xwrite

At least for me, this improves the readability of xread and xwrite; hopefully allowing missing "continue" statements to be spotted more easily.

Signed-off-by: Eric Wong <e@80x24.org>
---
 wrapper.c | 40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)
diff --git a/wrapper.c b/wrapper.c
index d973f86..04bb952 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -227,6 +227,20 @@ int xopen(const char *path, int oflag, ...)
 	}
 }
 
+static void io_wait(int fd, short poll_events)
+{
+	struct pollfd pfd;
+
+	pfd.fd = fd;
+	pfd.events = poll_events;
+
+	/*
+	 * no need to check for errors, here;
+	 * a subsequent read/write will detect unrecoverable errors
+	 */
+	poll(&pfd, 1, -1);
+}
+
 /*
  * xread() is the same a read(), but it automatically restarts read()
  * operations with a recoverable error (EAGAIN and EINTR). xread()
@@ -243,18 +257,7 @@ ssize_t xread(int fd, void *buf, size_t len)
 			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);
+				io_wait(fd, POLLIN);
 				continue;
 			}
 		}
@@ -278,18 +281,7 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
 			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);
+				io_wait(fd, POLLOUT);
 				continue;
 			}
 		}
-- 
EW
Previous: Jeff KingNext: Jeff King
Message 10 of 17 in “wrapper: xread/xwrite fixes for non-blocking FDs”
  1. 0/2 wrapper: xread/xwrite fixes for non-blocking FDsEric Wong, Jun 26, 2016
  2. 1/2 xread: retry after poll on EAGAIN/EWOULDBLOCKEric Wong, Jun 26, 2016
  3. Jeff KingJun 26, 2016
  4. Junio C HamanoJun 27, 2016
  5. Jeff KingJun 27, 2016
  6. Stefan BellerJun 27, 2016
  7. Jeff KingJun 27, 2016
  8. Stefan BellerJun 27, 2016
  9. Jeff KingJun 27, 2016
  10. Eric WongJun 27, 2016
  11. Jeff KingJun 27, 2016
  12. Jeff KingJun 27, 2016
  13. Eric WongJun 27, 2016
  14. Jeff KingJun 26, 2016
  15. 1/2 xread: retry after poll on EAGAIN/EWOULDBLOCKEric Wong, Jun 27, 2016
  16. 2/2 xwrite: poll on non-blocking FDsEric Wong, Jun 26, 2016
  17. Jeff KingJun 26, 2016

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.