From d19e18c68d6415214afad37ce6cb47ec038ebe1c Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Sun, 28 Apr 2013 17:47:43 -0700 Subject: 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. --- Src/Zle/zle_main.c | 10 ++++++++++ Src/init.c | 1 + Src/input.c | 2 ++ Src/signals.h | 8 ++++++++ Src/utils.c | 7 +++++++ 5 files changed, 28 insertions(+) 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 -- cgit 1.4.1