[zsh] apply upstream patch which fixes CPU load issue (RHBZ#1120424)

Dominic Hopf dmaphy at fedoraproject.org
Thu Jul 17 17:48:55 UTC 2014


commit 54f9ac239ca9d5e99c2c04c2c0ab2c152bbd65f2
Author: Dominic Hopf <dmaphy at fedoraproject.org>
Date:   Thu Jul 17 19:49:15 2014 +0200

    apply upstream patch which fixes CPU load issue (RHBZ#1120424)

 0001-zsh-fix-cpuload-issue.patch |  159 ++++++++++++++++++++++++++++++++++++++
 zsh.spec                         |   14 +++-
 2 files changed, 171 insertions(+), 2 deletions(-)
---
diff --git a/0001-zsh-fix-cpuload-issue.patch b/0001-zsh-fix-cpuload-issue.patch
new file mode 100644
index 0000000..3b063a0
--- /dev/null
+++ b/0001-zsh-fix-cpuload-issue.patch
@@ -0,0 +1,159 @@
+diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
+index 6d3bb4b..127b4c4 100644
+--- a/Doc/Zsh/zle.yo
++++ b/Doc/Zsh/zle.yo
+@@ -492,26 +492,35 @@ Only available if your system supports one of the `poll' or `select' system
+ calls; most modern systems do.
+ 
+ Installs var(handler) (the name of a shell function) to handle input from
+-file descriptor var(fd).  When zle is attempting to read data, it will
+-examine both the terminal and the list of handled var(fd)'s.  If data
+-becomes available on a handled var(fd), zle will call var(handler) with
+-the fd which is ready for reading as the only argument.  If the handler
+-produces output to the terminal, it should call `tt(zle -I)' before doing
+-so (see below).  The handler should not attempt to read from the terminal.
+-Note that zle makes no attempt to check whether this fd is actually
++file descriptor var(fd).  Installing a handler for an var(fd) which is
++already handled causes the existing handler to be replaced.  Any number of
++handlers for any number of readable file descriptors may be installed.
++Note that zle makes no attempt to check whether this var(fd) is actually
+ readable when installing the handler.  The user must make their own
+ arrangements for handling the file descriptor when zle is not active.
+ 
+-If the option tt(-w) is also given, the var(handler) is instead a
+-line editor widget, typically a shell function made into a widget using
+-tt(zle -N).  In that case var(handler) can use all the facilities of
+-zle to update the current editing line.  Note, however, that as handling
+-var(fd) takes place at a low level changes to the display will not
+-automatically appear; the widget should call tt(zle -R) to force redisplay.
+-
+-Any number of handlers for any number of readable file descriptors may be
+-installed.  Installing a handler for an var(fd) which is already handled
+-causes the existing handler to be replaced.
++When zle is attempting to read data, it will examine both the terminal and
++the list of handled var(fd)'s.  If data becomes available on a handled
++var(fd), zle calls var(handler) with the fd which is ready for reading
++as the first argument.  Under normal circumstances this is the only
++argument, but if an error was detected, a second argument provides
++details: `tt(hup)' for a disconnect, `tt(nval)' for a closed or otherwise
++invalid descriptor, or `tt(err)' for any other condition.  Systems that
++support only the `select' system call always use `tt(err)'.
++
++If the option tt(-w) is also given, the var(handler) is instead a line
++editor widget, typically a shell function made into a widget using
++`tt(zle -N)'.  In that case var(handler) can use all the facilities of zle
++to update the current editing line.  Note, however, that as handling var(fd)
++takes place at a low level changes to the display will not automatically
++appear; the widget should call `tt(zle -R)' to force redisplay.  As of this
++writing, widget handlers only support a single argument and thus are never
++passed a string for error state, so widgets must be prepared to test the
++descriptor themselves.
++
++If either type of handler produces output to the terminal, it should call
++`tt(zle -I)' before doing so (see below).  Handlers should not attempt to
++read from the terminal.
+ 
+ If no var(handler) is given, but an var(fd) is present, any handler for
+ that var(fd) is removed.  If there is none, an error message is printed
+@@ -526,7 +535,8 @@ silently return status 1.
+ 
+ Note that this feature should be used with care.  Activity on one of the
+ var(fd)'s which is not properly handled can cause the terminal to become
+-unusable.
++unusable.  Removing an var(fd) handler from within a signal trap may cause
++unpredictable behavior.
+ 
+ Here is a simple example of using this feature.  A connection to a remote
+ TCP port is created using the ztcp command; see 
+@@ -536,6 +546,7 @@ which simply prints out any data which arrives on this connection.  Note
+ that `select' will indicate that the file descriptor needs handling
+ if the remote side has closed the connection; we handle that by testing
+ for a failed read.
++
+ example(if ztcp pwspc 2811; then
+   tcpfd=$REPLY
+   handler+LPAR()RPAR() {
+diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
+index b0010fc..442c319 100644
+--- a/Src/Zle/zle_main.c
++++ b/Src/Zle/zle_main.c
+@@ -525,7 +525,8 @@ raw_getbyte(long do_keytmout, char *cptr)
+ #endif
+ #ifndef HAVE_POLL
+ # ifdef HAVE_SELECT
+-    fd_set foofd;
++    fd_set foofd, errfd;
++    FD_ZERO(&errfd);
+ # endif
+ #endif
+ 
+@@ -613,11 +614,14 @@ raw_getbyte(long do_keytmout, char *cptr)
+ 	    if (!errtry) {
+ 		for (i = 0; i < nwatch; i++) {
+ 		    int fd = watch_fds[i].fd;
++		    if (FD_ISSET(fd, &errfd))
++			continue;
+ 		    FD_SET(fd, &foofd);
+ 		    if (fd > fdmax)
+ 			fdmax = fd;
+ 		}
+ 	    }
++	    FD_ZERO(&errfd);
+ 
+ 	    if (tmout.tp != ZTM_NONE) {
+ 		expire_tv.tv_sec = tmout.exp100ths / 100;
+@@ -732,9 +736,10 @@ raw_getbyte(long do_keytmout, char *cptr)
+ 		    Watch_fd lwatch_fd = lwatch_fds + i;
+ 		    if (
+ # ifdef HAVE_POLL
+-			(fds[i+1].revents & POLLIN)
++			(fds[i+1].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))
+ # else
+-			FD_ISSET(lwatch_fd->fd, &foofd)
++			FD_ISSET(lwatch_fd->fd, &foofd) ||
++			FD_ISSET(lwatch_fd->fd, &errfd)
+ # endif
+ 			) {
+ 			/* Handle the fd. */
+@@ -765,6 +770,9 @@ raw_getbyte(long do_keytmout, char *cptr)
+ 			    if (fds[i+1].revents & POLLNVAL)
+ 				zaddlinknode(funcargs, ztrdup("nval"));
+ #  endif
++# else
++			    if (FD_ISSET(lwatch_fd->fd, &errfd))
++				zaddlinknode(funcargs, ztrdup("err"));
+ # endif
+ 			    callhookfunc(lwatch_fd->func, funcargs, 0, NULL);
+ 			    freelinklist(funcargs, freestr);
+@@ -786,6 +794,31 @@ raw_getbyte(long do_keytmout, char *cptr)
+ 		for (i = 0; i < lnwatch; i++)
+ 		    zsfree(lwatch_fds[i].func);
+ 		zfree(lwatch_fds, lnwatch*sizeof(struct watch_fd));
++
++# ifdef HAVE_POLL
++		/* Function may have added or removed handlers */
++		nfds = 1 + nwatch;
++		if (nfds > 1) {
++		    fds = zrealloc(fds, sizeof(struct pollfd) * nfds);
++		    for (i = 0; i < nwatch; i++) {
++			/*
++			 * This is imperfect because it assumes fds[] and
++			 * watch_fds[] remain in sync, which may be false
++			 * if handlers are shuffled.  However, it should
++			 * be harmless (e.g., produce one extra pass of
++			 * the loop) in the event they fall out of sync.
++			 */
++			if (fds[i+1].fd == watch_fds[i].fd &&
++			    (fds[i+1].revents & (POLLERR|POLLHUP|POLLNVAL))) {
++			    fds[i+1].events = 0;	/* Don't poll this */
++			} else {
++			    fds[i+1].fd = watch_fds[i].fd;
++			    fds[i+1].events = POLLIN;
++			}
++			fds[i+1].revents = 0;
++		    }
++		}
++# endif
+ 	    }
+ 	}
+ # ifdef HAVE_POLL
diff --git a/zsh.spec b/zsh.spec
index ceb76ac..81f434c 100644
--- a/zsh.spec
+++ b/zsh.spec
@@ -3,7 +3,7 @@
 Summary: Powerful interactive shell
 Name: zsh
 Version: 5.0.5
-Release: 6%{?dist}
+Release: 7%{?dist}
 License: MIT
 URL: http://zsh.sourceforge.net/
 Group: System Environment/Shells
@@ -18,7 +18,13 @@ Source7: zshprompt.pl
 # Give me better tools or die!
 %global _default_patch_fuzz 2
 Patch0: zsh-serial.patch
+
+# Already applied upstream, can be removed with next upstream release
 Patch1: 0000-zsh-fix-runhelpdir-issue.patch
+
+# Already applied upstream, can be removed with next upstream release
+Patch2: 0001-zsh-fix-cpuload-issue.patch 
+
 Patch4: zsh-4.3.6-8bit-prompts.patch
 Patch5: zsh-test-C02-dev_fd-mock.patch
 Patch12: http://ausil.fedorapeople.org/aarch64/zsh/zsh-aarch64.patch
@@ -57,6 +63,7 @@ This package contains the Zsh manual in html format.
 %setup -q
 %patch0 -p1 -b .serial
 %patch1 -p1
+%patch2 -p1
 %patch4 -p1
 %patch5 -p1
 
@@ -121,7 +128,7 @@ for i in checkmail harden run-help zcalc zkbd; do
 done
 
 sed -i "s!$RPM_BUILD_ROOT%{_datadir}/%{name}/%{version}/help!%{_datadir}/%{name}/%{version}/help!" \
-	$RPM_BUILD_ROOT%{_datadir}/zsh/%{version}/functions/{run-help,_run-help}
+    $RPM_BUILD_ROOT%{_datadir}/zsh/%{version}/functions/{run-help,_run-help}
 
 
 %clean
@@ -178,6 +185,9 @@ fi
 %doc Doc/*.html
 
 %changelog
+* Thu Jul 17 2014 Dominic Hopf <dmaphy at fedoraproject.org> - 5.0.5-7
+- apply upstream patch which fixes CPU load issue (RHBZ#1120424)
+
 * Wed Jul 09 2014 Adam Jackson <ajax at redhat.com> 5.0.5-6
 - Fix missing 'fi' in %%post
 


More information about the scm-commits mailing list