about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2013-04-28 17:47:43 -0700
committerBart Schaefer <schaefer@zsh.org>2013-04-30 00:08:49 -0700
commitd19e18c68d6415214afad37ce6cb47ec038ebe1c (patch)
treec325d0ca0440246d07b758c25a20d6c5f49356b4
parentcbf6f144a942a3db27025e68357b9fd8ca442ed8 (diff)
downloadzsh-d19e18c68d6415214afad37ce6cb47ec038ebe1c.tar.gz
zsh-d19e18c68d6415214afad37ce6cb47ec038ebe1c.tar.xz
zsh-d19e18c68d6415214afad37ce6cb47ec038ebe1c.zip
31350: block SIGWINCH nearly all the time, except
when about to calculate prompts or do synchronous read, so
syscalls are not interrupted by window size changes.
-rw-r--r--Src/Zle/zle_main.c10
-rw-r--r--Src/init.c1
-rw-r--r--Src/input.c2
-rw-r--r--Src/signals.h8
-rw-r--r--Src/utils.c7
5 files changed, 28 insertions, 0 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 9a4265f06..569ad5f5a 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -567,7 +567,9 @@ raw_getbyte(long do_keytmout, char *cptr)
 	gettyinfo(&ti);
 	ti.tio.c_cc[VMIN] = 0;
 	settyinfo(&ti);
+	winch_unblock();
 	ret = read(SHTTY, cptr, 1);
+	winch_block();
 	ti.tio.c_cc[VMIN] = 1;
 	settyinfo(&ti);
 	if (ret > 0)
@@ -597,7 +599,9 @@ raw_getbyte(long do_keytmout, char *cptr)
 	    else
 		poll_timeout = -1;
 
+	    winch_unblock();
 	    selret = poll(fds, errtry ? 1 : nfds, poll_timeout);
+	    winch_block();
 # else
 	    int fdmax = SHTTY;
 	    struct timeval *tvptr;
@@ -622,8 +626,10 @@ raw_getbyte(long do_keytmout, char *cptr)
 	    else
 		tvptr = NULL;
 
+	    winch_unblock();
 	    selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd,
 			    NULL, NULL, tvptr);
+	    winch_block();
 # endif
 	    /*
 	     * Make sure a user interrupt gets passed on straight away.
@@ -788,7 +794,9 @@ raw_getbyte(long do_keytmout, char *cptr)
 #  else
 	ioctl(SHTTY, TCSETA, &ti.tio);
 #  endif
+	winch_unblock();
 	ret = read(SHTTY, cptr, 1);
+	winch_block();
 #  ifdef HAVE_TERMIOS_H
 	tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
 #  else
@@ -799,7 +807,9 @@ raw_getbyte(long do_keytmout, char *cptr)
 #endif
     }
 
+    winch_unblock();
     ret = read(SHTTY, cptr, 1);
+    winch_block();
 
     return ret;
 }
diff --git a/Src/init.c b/Src/init.c
index 8467a739c..f4fb3bee4 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1113,6 +1113,7 @@ init_signals(void)
     install_handler(SIGCHLD);
 #ifdef SIGWINCH
     install_handler(SIGWINCH);
+    winch_block();	/* See utils.c:preprompt() */
 #endif
     if (interact) {
 	install_handler(SIGALRM);
diff --git a/Src/input.c b/Src/input.c
index 5cff22da4..9bd9663bf 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -143,10 +143,12 @@ shingetline(void)
 
     p = buf;
     for (;;) {
+	winch_unblock();
 	do {
 	    errno = 0;
 	    c = fgetc(bshin);
 	} while (c < 0 && errno == EINTR);
+	winch_block();
 	if (c < 0 || c == '\n') {
 	    if (c == '\n')
 		*p++ = '\n';
diff --git a/Src/signals.h b/Src/signals.h
index 9541a1a02..d68096891 100644
--- a/Src/signals.h
+++ b/Src/signals.h
@@ -59,6 +59,14 @@
 #define child_block()      signal_block(sigchld_mask)
 #define child_unblock()    signal_unblock(sigchld_mask)
 
+#ifdef SIGWINCH
+# define winch_block()      signal_block(signal_mask(SIGWINCH))
+# define winch_unblock()    signal_unblock(signal_mask(SIGWINCH))
+#else
+# define winch_block()      0
+# define winch_unblock()    0
+#endif
+
 /* ignore a signal */
 #define signal_ignore(S)   signal(S, SIG_IGN)
 
diff --git a/Src/utils.c b/Src/utils.c
index 26e2a5c2c..94ae52284 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1291,6 +1291,13 @@ preprompt(void)
     int period = getiparam("PERIOD");
     int mailcheck = getiparam("MAILCHECK");
 
+    /*
+     * Handle any pending window size changes before we compute prompts,
+     * then block them again to avoid interrupts during prompt display.
+     */
+    winch_unblock();
+    winch_block();
+
     if (isset(PROMPTSP) && isset(PROMPTCR) && !use_exit_printed && shout) {
 	/* The PROMPT_SP heuristic will move the prompt down to a new line
 	 * if there was any dangling output on the line (assuming the terminal