Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Oct 2011 11:10:12 +0000 (UTC)
From:      Mikolaj Golub <trociny@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r225968 - stable/7/usr.bin/script
Message-ID:  <201110041110.p94BACvW054868@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trociny
Date: Tue Oct  4 11:10:11 2011
New Revision: 225968
URL: http://svn.freebsd.org/changeset/base/225968

Log:
  MFC r225809:
  
  When script(1) reads EOF from input it starts spinning on zero-byte
  reads eating 100% CPU. Fix this by skipping select on STDIN after
  reading EOF -- permanently if STDIN is not terminal and for one second
  if it is.
  
  Also after reading EOF from STDIN we have to pass it to the program
  being scripted. The previous approach was to write zero bytes into the
  pseudo-terminal. This does not work because zero-byte write does not
  have any effect on read. Fix this by sending VEOF instead.
  
  Reported by:	Ronald Klop <ronald-freebsd8@klop.yi.org>
  Discussed with:	kib, Chris Torek <chris.torek@gmail.com>

Modified:
  stable/7/usr.bin/script/script.1
  stable/7/usr.bin/script/script.c
Directory Properties:
  stable/7/usr.bin/script/   (props changed)

Modified: stable/7/usr.bin/script/script.1
==============================================================================
--- stable/7/usr.bin/script/script.1	Tue Oct  4 11:08:44 2011	(r225967)
+++ stable/7/usr.bin/script/script.1	Tue Oct  4 11:10:11 2011	(r225968)
@@ -170,3 +170,12 @@ The slave terminal mode is checked
 for ECHO mode to check when to avoid manual echo logging.
 This does not
 work when in a raw mode where the program being run is doing manual echo.
+.Pp
+If the
+.Nm
+reads zero bytes from the terminal it switches to a mode when it probes read
+only once a second until it gets some data.
+This prevents the
+.Nm
+spinning on zero-byte reads, but might cause a 1-second delay in
+processing of the user input.

Modified: stable/7/usr.bin/script/script.c
==============================================================================
--- stable/7/usr.bin/script/script.c	Tue Oct  4 11:08:44 2011	(r225967)
+++ stable/7/usr.bin/script/script.c	Tue Oct  4 11:10:11 2011	(r225968)
@@ -91,6 +91,7 @@ main(int argc, char *argv[])
 	char ibuf[BUFSIZ];
 	fd_set rfd;
 	int flushtime = 30;
+	int readstdin;
 
 	aflg = kflg = 0;
 	while ((ch = getopt(argc, argv, "aqkt:")) != -1)
@@ -159,19 +160,21 @@ main(int argc, char *argv[])
 	if (child == 0)
 		doshell(argv);
 
-	if (flushtime > 0)
-		tvp = &tv;
-	else
-		tvp = NULL;
-
-	start = time(0);
-	FD_ZERO(&rfd);
+	start = tvec = time(0);
+	readstdin = 1;
 	for (;;) {
+		FD_ZERO(&rfd);
 		FD_SET(master, &rfd);
-		FD_SET(STDIN_FILENO, &rfd);
-		if (flushtime > 0) {
-			tv.tv_sec = flushtime;
+		if (readstdin)
+			FD_SET(STDIN_FILENO, &rfd);
+		if ((!readstdin && ttyflg) || flushtime > 0) {
+			tv.tv_sec = !readstdin && ttyflg ? 1 :
+			    flushtime - (tvec - start);
 			tv.tv_usec = 0;
+			tvp = &tv;
+			readstdin = 1;
+		} else {
+			tvp = NULL;
 		}
 		n = select(master + 1, &rfd, 0, 0, tvp);
 		if (n < 0 && errno != EINTR)
@@ -180,8 +183,13 @@ main(int argc, char *argv[])
 			cc = read(STDIN_FILENO, ibuf, BUFSIZ);
 			if (cc < 0)
 				break;
-			if (cc == 0)
-				(void)write(master, ibuf, 0);
+			if (cc == 0) {
+				if (tcgetattr(master, &stt) == 0 &&
+				    (stt.c_lflag & ICANON) != 0) {
+					(void)write(master, &stt.c_cc[VEOF], 1);
+				}
+				readstdin = 0;
+			}
 			if (cc > 0) {
 				(void)write(master, ibuf, cc);
 				if (kflg && tcgetattr(master, &stt) >= 0 &&



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201110041110.p94BACvW054868>