diff options
author | Bart Schaefer <schaefer@zsh.org> | 2013-04-28 17:47:43 -0700 |
---|---|---|
committer | Bart Schaefer <schaefer@zsh.org> | 2013-04-30 00:08:49 -0700 |
commit | d19e18c68d6415214afad37ce6cb47ec038ebe1c (patch) | |
tree | c325d0ca0440246d07b758c25a20d6c5f49356b4 | |
parent | cbf6f144a942a3db27025e68357b9fd8ca442ed8 (diff) | |
download | zsh-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.c | 10 | ||||
-rw-r--r-- | Src/init.c | 1 | ||||
-rw-r--r-- | Src/input.c | 2 | ||||
-rw-r--r-- | Src/signals.h | 8 | ||||
-rw-r--r-- | Src/utils.c | 7 |
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 |