From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11863 invoked by alias); 29 Apr 2013 01:03:57 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 31350 Received: (qmail 19013 invoked from network); 29 Apr 2013 01:03:55 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <130428180338.ZM14577@torch.brasslantern.com> Date: Sun, 28 Apr 2013 18:03:38 -0700 In-reply-to: <517D40B0.8020609@thregr.org> Comments: In reply to "Yuri D'Elia" "Re: precmd: write error: interrupted" (Apr 28, 5:30pm) References: <130425111646.ZM17258@torch.brasslantern.com> <130426080805.ZM18619@torch.brasslantern.com> <517C0E09.4040505@users.sourceforge.net> <130427153141.ZM20125@torch.brasslantern.com> <517D40B0.8020609@thregr.org> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: precmd: write error: interrupted MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Apr 28, 5:30pm, Yuri D'Elia wrote: } Subject: Re: precmd: write error: interrupted } } > + signal_block(signal_mask(SIGWINCH)); /* See zleread() */ } > callhookfunc("precmd", NULL, 1, NULL); } > + signal_unblock(signal_mask(SIGWINCH)); } } This is going to solve the issue for "precmd" only though, not the } SIGWHINCH issue as a whole. True; I was trying to creep up on it incrementally. Incidentally even queue_signals() doesn't actually block the signals, it just doesn't call anything below the top-level handler, so I suspect that replacing the above with queue_signals() would still show the bug. Here's a stab at a more comprehensive patch. This follows the pattern of child_block()/child_unblock() which we use elsewhere to reap children only when safe to do so. I'm not 100% confident that this does the right thing for non-interactive shells/sourcing of scripts, but I *think* the change in shingetline() should cover those cases. diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 9a4265f..569ad5f 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 8467a73..f4fb3be 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 5cff22d..9bd9663 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 9541a1a..d680968 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 26e2a5c..94ae522 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 -- 1.7.9.6 (Apple Git-31.1)