[git commit] nc_bloaty: use poll() instead of select()

Denys Vlasenko vda.linux at googlemail.com
Fri Feb 17 16:48:59 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=94dcfd8cc065b699081984d6f4b4bbfc811937b1
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
readwrite                                            829     715    -114

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/nc_bloaty.c | 55 ++++++++++++++++++++++----------------------------
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index 192e42f..f8c3753 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -582,11 +582,10 @@ void oprint(int direction, unsigned char *p, unsigned bc);
 #endif
 
 /* readwrite:
- handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
+ handle stdin/stdout/network I/O.  Bwahaha!! -- the i/o loop from hell.
  In this instance, return what might become our exit status. */
 static int readwrite(void)
 {
-	int rr;
 	char *zp = zp; /* gcc */  /* stdin buf ptr */
 	char *np = np;            /* net-in buf ptr */
 	unsigned rzleft;
@@ -594,45 +593,41 @@ static int readwrite(void)
 	unsigned netretry;              /* net-read retry counter */
 	unsigned fds_open;
 
-	/* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
-	 either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
-	fd_set ding1;                   /* for select loop */
-	fd_set ding2;
-	FD_ZERO(&ding1);
-	FD_SET(netfd, &ding1);
-	FD_SET(STDIN_FILENO, &ding1);
-	fds_open = 2;
+	struct pollfd pfds[2];
+	pfds[0].fd = STDIN_FILENO;
+	pfds[0].events = POLLIN;
+	pfds[1].fd = netfd;
+	pfds[1].events = POLLIN;
 
+	fds_open = 2;
 	netretry = 2;
 	rzleft = rnleft = 0;
 	if (o_interval)
 		sleep(o_interval);                /* pause *before* sending stuff, too */
 
-	/* and now the big ol' select shoveling loop ... */
+	/* and now the big ol' shoveling loop ... */
 	/* nc 1.10 has "while (FD_ISSET(netfd)" here */
 	while (fds_open) {
+		int rr;
+		int poll_tmout_ms;
 		unsigned wretry = 8200;               /* net-write sanity counter */
 
-		ding2 = ding1;                        /* FD_COPY ain't portable... */
-	/* some systems, notably linux, crap into their select timers on return, so
-	 we create a expendable copy and give *that* to select.  */
+		poll_tmout_ms = -1;
 		if (o_wait) {
-			struct timeval tmp_timer;
-			tmp_timer.tv_sec = o_wait;
-			tmp_timer.tv_usec = 0;
-		/* highest possible fd is netfd (3) */
-			rr = select(netfd+1, &ding2, NULL, NULL, &tmp_timer);
-		} else
-			rr = select(netfd+1, &ding2, NULL, NULL, NULL);
+			poll_tmout_ms = INT_MAX;
+			if (o_wait < INT_MAX / 1000)
+				poll_tmout_ms = o_wait * 1000;
+		}
+		rr = poll(pfds, 2, poll_tmout_ms);
 		if (rr < 0 && errno != EINTR) {                /* might have gotten ^Zed, etc */
-			holler_perror("select");
+			holler_perror("poll");
 			close(netfd);
 			return 1;
 		}
 	/* if we have a timeout AND stdin is closed AND we haven't heard anything
 	 from the net during that time, assume it's dead and close it too. */
 		if (rr == 0) {
-			if (!FD_ISSET(STDIN_FILENO, &ding1)) {
+			if (!pfds[0].revents) {
 				netretry--;                        /* we actually try a coupla times. */
 				if (!netretry) {
 					if (o_verbose > 1)         /* normally we don't care */
@@ -641,19 +636,17 @@ static int readwrite(void)
 					return 0;                  /* not an error! */
 				}
 			}
-		} /* select timeout */
-	/* xxx: should we check the exception fds too?  The read fds seem to give
-	 us the right info, and none of the examples I found bothered. */
+		} /* timeout */
 
 	/* Ding!!  Something arrived, go check all the incoming hoppers, net first */
-		if (FD_ISSET(netfd, &ding2)) {                /* net: ding! */
+		if (pfds[1].revents) {                /* net: ding! */
 			rr = read(netfd, bigbuf_net, BIGSIZ);
 			if (rr <= 0) {
 				if (rr < 0 && o_verbose > 1) {
 					/* nc 1.10 doesn't do this */
 					bb_perror_msg("net read");
 				}
-				FD_CLR(netfd, &ding1);                /* net closed */
+				pfds[1].fd = -1;                   /* don't poll for netfd anymore */
 				fds_open--;
 				rzleft = 0;                        /* can't write anymore: broken pipe */
 			} else {
@@ -669,12 +662,12 @@ Debug("got %d from the net, errno %d", rr, errno);
 			goto shovel;
 
 	/* okay, suck more stdin */
-		if (FD_ISSET(STDIN_FILENO, &ding2)) {                /* stdin: ding! */
+		if (pfds[0].revents) {                /* stdin: ding! */
 			rr = read(STDIN_FILENO, bigbuf_in, BIGSIZ);
 	/* Considered making reads here smaller for UDP mode, but 8192-byte
 	 mobygrams are kinda fun and exercise the reassembler. */
 			if (rr <= 0) {                        /* at end, or fukt, or ... */
-				FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */
+				pfds[0].fd = -1;              /* disable stdin */
 				/*close(STDIN_FILENO); - not really necessary */
 				/* Let peer know we have no more data */
 				/* nc 1.10 doesn't do this: */
@@ -718,7 +711,7 @@ Debug("wrote %d to net, errno %d", rr, errno);
 		} /* rzleft */
 		if (o_interval) {                        /* cycle between slow lines, or ... */
 			sleep(o_interval);
-			continue;                        /* ...with hairy select loop... */
+			continue;                        /* ...with hairy loop... */
 		}
 		if (rzleft || rnleft) {                  /* shovel that shit till they ain't */
 			wretry--;                        /* none left, and get another load */


More information about the busybox-cvs mailing list