about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2000-11-11 19:50:27 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2000-11-11 19:50:27 +0000
commitc292a3ae50bd0605b015f80266418e391c3c10fe (patch)
tree8f2baf5a9e1cb7a9615190025d9825ed9824f952 /Src
parent89d480f57d59a794d8c2e04fc5270bed13b7a28a (diff)
downloadzsh-c292a3ae50bd0605b015f80266418e391c3c10fe.tar.gz
zsh-c292a3ae50bd0605b015f80266418e391c3c10fe.tar.xz
zsh-c292a3ae50bd0605b015f80266418e391c3c10fe.zip
Sven: 13108: Handle traps synchronously
pws: 13109, 13111: clear up zle display when output produced in trap.
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/zftp.c20
-rw-r--r--Src/Modules/zpty.c4
-rw-r--r--Src/Zle/zle_main.c19
-rw-r--r--Src/Zle/zle_thingy.c16
-rw-r--r--Src/builtin.c12
-rw-r--r--Src/exec.c22
-rw-r--r--Src/init.c3
-rw-r--r--Src/input.c4
-rw-r--r--Src/jobs.c14
-rw-r--r--Src/signals.c72
-rw-r--r--Src/signals.h35
-rw-r--r--Src/utils.c30
-rw-r--r--Src/zsh.h2
13 files changed, 199 insertions, 54 deletions
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index e39994733..ef37dbdc7 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -801,7 +801,7 @@ zfgetline(char *ln, int lnsize, int tmout)
 		cmdbuf[0] = (char)IAC;
 		cmdbuf[1] = (char)DONT;
 		cmdbuf[2] = ch;
-		write(zfsess->cfd, cmdbuf, 3);
+		ztrapwrite(zfsess->cfd, cmdbuf, 3);
 		continue;
 
 	    case DO:
@@ -811,7 +811,7 @@ zfgetline(char *ln, int lnsize, int tmout)
 		cmdbuf[0] = (char)IAC;
 		cmdbuf[1] = (char)WONT;
 		cmdbuf[2] = ch;
-		write(zfsess->cfd, cmdbuf, 3);
+		ztrapwrite(zfsess->cfd, cmdbuf, 3);
 		continue;
 
 	    case EOF:
@@ -996,7 +996,7 @@ zfsendcmd(char *cmd)
 	return 6;
     }
     zfalarm(tmout);
-    ret = write(zfsess->cfd, cmd, strlen(cmd));
+    ret = ztrapwrite(zfsess->cfd, cmd, strlen(cmd));
     alarm(0);
 
     if (ret <= 0) {
@@ -1470,7 +1470,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
     int ret;
 
     if (!tmout)
-	return read(fd, bf, sz);
+	return ztrapread(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1479,7 +1479,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
     }
     zfalarm(tmout);
 
-    ret = read(fd, bf, sz);
+    ret = ztrapread(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -1495,7 +1495,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
     int ret;
 
     if (!tmout)
-	return write(fd, bf, sz);
+	return ztrapwrite(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1504,7 +1504,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
     }
     zfalarm(tmout);
 
-    ret = write(fd, bf, sz);
+    ret = ztrapwrite(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -2846,7 +2846,7 @@ zfclose(int leaveparams)
 	if (!zfnopen) {
 	    /* Write the final status in case this is a subshell */
 	    lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	    write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
+	    ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
 
 	    close(zfstatfd);
 	    zfstatfd = -1;
@@ -3123,7 +3123,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
 	/* Get the status in case it was set by a forked process */
 	int oldstatus = zfstatusp[zfsessno];
 	lseek(zfstatfd, 0, 0);
-	read(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
+	ztrapread(zfstatfd, zfstatusp, sizeof(int)*zfsesscnt);
 	if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
 	    /* got closed in subshell without us knowing */
 	    zcfinish = 2;
@@ -3212,7 +3212,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
 	 * but only for the active session.
 	 */
 	lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	write(zfstatfd, zfstatusp+zfsessno, sizeof(int));
+	ztrapwrite(zfstatfd, zfstatusp+zfsessno, sizeof(int));
     }
     return ret;
 }
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index d25c3a865..e76411a8b 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -536,7 +536,7 @@ ptywritestr(Ptycmd cmd, char *s, int len)
 
     for (; !errflag && !breaks && !retflag && !contflag && len;
 	 len -= written, s += written) {
-	if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock &&
+	if ((written = ztrapwrite(cmd->fd, s, len)) < 0 && cmd->nblock &&
 #ifdef EWOULDBLOCK
 	    errno == EWOULDBLOCK
 #else
@@ -578,7 +578,7 @@ ptywrite(Ptycmd cmd, char **args, int nonl)
 	int n;
 	char buf[BUFSIZ];
 
-	while ((n = read(0, buf, BUFSIZ)) > 0)
+	while ((n = ztrapread(0, buf, BUFSIZ)) > 0)
 	    if (ptywritestr(cmd, buf, n))
 		return 1;
     }
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index b2d075f91..b2a662072 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -313,11 +313,17 @@ static int
 breakread(int fd, char *buf, int n)
 {
     fd_set f;
+    int ret;
 
     FD_ZERO(&f);
     FD_SET(fd, &f);
-    return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
-	    EOF : read(fd, buf, n));
+
+    ALLOWTRAPS {
+	ret = (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
+	       EOF : read(fd, buf, n));
+    } DISALLOWTRAPS;
+
+    return ret;
 }
 
 # define read    breakread
@@ -388,7 +394,7 @@ getkey(int keytmout)
 #  else
 	    ioctl(SHTTY, TCSETA, &ti.tio);
 #  endif
-	    r = read(SHTTY, &cc, 1);
+	    r = ztrapread(SHTTY, &cc, 1);
 #  ifdef HAVE_TERMIOS_H
 	    tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
 #  else
@@ -398,7 +404,10 @@ getkey(int keytmout)
 # endif
 #endif
 	}
-	while ((r = read(SHTTY, &cc, 1)) != 1) {
+	for (;;) {
+	    r = ztrapread(SHTTY, &cc, 1);
+	    if (r == 1)
+		break;
 	    if (r == 0) {
 		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
 		   that were typed while commands are running.  Unfortuantely
@@ -1083,7 +1092,7 @@ zleaftertrap(Hookdef dummy, void *dat)
 static struct builtin bintab[] = {
     BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaU", NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaUI", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index 7e81e2f88..f5acb73b4 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -339,6 +339,7 @@ bin_zle(char *name, char **args, char *ops, int func)
 	{ 'R', bin_zle_refresh, 0, -1 },
 	{ 'M', bin_zle_mesg, 1, 1 },
 	{ 'U', bin_zle_unget, 1, 1 },
+	{ 'I', bin_zle_invalidate, 0, 0 },
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -396,10 +397,8 @@ bin_zle_refresh(char *name, char **args, char *ops, char func)
     char *s = statusline;
     int sl = statusll, ocl = clearlist;
 
-    if (!zleactive) {
-	zwarnnam(name, "can only be called from widget function", NULL, 0);
+    if (!zleactive)
 	return 1;
-    }
     statusline = NULL;
     statusll = 0;
     if (*args) {
@@ -656,6 +655,17 @@ bin_zle_call(char *name, char **args, char *ops, char func)
     return ret;
 }
 
+/**/
+static int
+bin_zle_invalidate(char *name, char **args, char *ops, char func)
+{
+    if (zleactive) {
+	trashzle();
+	return 0;
+    } else
+	return 1;
+}
+
 /*******************/
 /* initialiasation */
 /*******************/
diff --git a/Src/builtin.c b/Src/builtin.c
index afd140d3c..d1cea8393 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -3218,7 +3218,7 @@ zexit(int val, int from_signal)
 	    checkjobs();   /* check if any jobs are running/stopped */
 	if (stopmsg) {
 	    stopmsg = 2;
-	    LASTALLOC_RETURN;
+	    return;
 	}
     }
     if (in_exit++ && from_signal)
@@ -3240,7 +3240,7 @@ zexit(int val, int from_signal)
 	}
     }
     if (sigtrapped[SIGEXIT])
-	dotrap(SIGEXIT);
+	dotrap(SIGEXIT, 1);
     runhookdef(EXITHOOK, NULL);
     if (mypid != getpid())
 	_exit(val);
@@ -3486,7 +3486,7 @@ bin_read(char *name, char **args, char *ops, int func)
 		    *bptr = readchar;
 		    val = 1;
 		    readchar = -1;
-		} else if ((val = read(readfd, bptr, nchars)) <= 0)
+		} else if ((val = ztrapread(readfd, bptr, nchars)) <= 0)
 		    break;
 	    
 		/* decrement number of characters read from number required */
@@ -3500,7 +3500,7 @@ bin_read(char *name, char **args, char *ops, int func)
 	if (!izle && !ops['u'] && !ops['p']) {
 	    /* dispose of result appropriately, etc. */
 	    if (isem)
-		while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
+		while (val > 0 && ztrapread(SHTTY, &d, 1) == 1 && d != '\n');
 	    else
 		settyinfo(&shttyinfo);
 	    if (haso) {
@@ -3733,6 +3733,7 @@ static int
 zread(int izle, int *readchar)
 {
     char cc, retry = 0;
+    int ret;
 
     if (izle) {
 	int c = getkeyptr(0);
@@ -3756,7 +3757,8 @@ zread(int izle, int *readchar)
     }
     for (;;) {
 	/* read a character from readfd */
-	switch (read(readfd, &cc, 1)) {
+	ret = ztrapread(readfd, &cc, 1);
+	switch (ret) {
 	case 1:
 	    /* return the character read */
 	    return STOUC(cc);
diff --git a/Src/exec.c b/Src/exec.c
index d0787f222..267625807 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -738,6 +738,7 @@ static int
 execsimple(Estate state)
 {
     wordcode code = *state->pc++;
+    int lv;
 
     if (errflag)
 	return (lastval = 1);
@@ -754,9 +755,13 @@ execsimple(Estate state)
 	    fputc('\n', xtrerr);
 	    fflush(xtrerr);
 	}
-	return (lastval = (errflag ? errflag : cmdoutval));
+	lv = (errflag ? errflag : cmdoutval);
     } else
-	return (lastval = (execfuncs[code - WC_CURSH])(state, 0));
+	lv = (execfuncs[code - WC_CURSH])(state, 0);
+
+    RUNTRAPS();
+
+    return lastval = lv;
 }
 
 /* Main routine for executing a list.                                *
@@ -887,19 +892,19 @@ sublist_done:
 	noerrexit = oldnoerrexit;
 
 	if (sigtrapped[SIGDEBUG])
-	    dotrap(SIGDEBUG);
+	    dotrap(SIGDEBUG, 1);
 
 	/* Check whether we are suppressing traps/errexit *
 	 * (typically in init scripts) and if we haven't  *
 	 * already performed them for this sublist.       */
 	if (!noerrexit && !donetrap) {
 	    if (sigtrapped[SIGZERR] && lastval) {
-		dotrap(SIGZERR);
+		dotrap(SIGZERR, 1);
 		donetrap = 1;
 	    }
 	    if (lastval && isset(ERREXIT)) {
 		if (sigtrapped[SIGEXIT])
-		    dotrap(SIGEXIT);
+		    dotrap(SIGEXIT, 1);
 		if (mypid != getpid())
 		    _exit(lastval);
 		else
@@ -1181,9 +1186,10 @@ execpline2(Estate state, wordcode pcode,
 	else
 	    list_pipe_text[0] = '\0';
     }
-    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END)
+    if (WC_PIPE_TYPE(pcode) == WC_PIPE_END) {
 	execcmd(state, input, output, how, last1 ? 1 : 2);
-    else {
+	RUNTRAPS();
+    } else {
 	int old_list_pipe = list_pipe;
 	Wordcode next = state->pc + (*state->pc);
 	wordcode code;
@@ -1218,12 +1224,14 @@ execpline2(Estate state, wordcode pcode,
 		entersubsh(how, 2, 0);
 		close(synch[1]);
 		execcmd(state, input, pipes[1], how, 0);
+		RUNTRAPS();
 		_exit(lastval);
 	    }
 	} else {
 	    /* otherwise just do the pipeline normally. */
 	    subsh_close = pipes[0];
 	    execcmd(state, input, pipes[1], how, 0);
+	    RUNTRAPS();
 	}
 	zclose(pipes[1]);
 	state->pc = next;
diff --git a/Src/init.c b/Src/init.c
index 341173889..290384c1a 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -170,7 +170,7 @@ loop(int toplevel, int justonce)
 	}
 	if (isset(SINGLECOMMAND) && toplevel) {
 	    if (sigtrapped[SIGEXIT])
-		dotrap(SIGEXIT);
+		dotrap(SIGEXIT, 1);
 	    exit(lastval);
 	}
 	if (justonce)
@@ -1107,6 +1107,7 @@ fallback_zleread(char *lp, char *rp, int ha)
     pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
     write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
     free(pptbuf);
+
     return (unsigned char *)shingetline();
 }
 
diff --git a/Src/input.c b/Src/input.c
index 8f33e3631..e82d25011 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -141,7 +141,9 @@ shingetline(void)
     for (;;) {
 	do {
 	    errno = 0;
-	    c = fgetc(bshin);
+	    ALLOWTRAPS {
+		c = fgetc(bshin);
+	    } DISALLOWTRAPS;
 	} while (c < 0 && errno == EINTR);
 	if (c < 0 || c == '\n') {
 	    if (c == '\n')
diff --git a/Src/jobs.c b/Src/jobs.c
index a938e774b..28246d422 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -378,7 +378,7 @@ update_job(Job jn)
 	    zrefresh();
     }
     if (sigtrapped[SIGCHLD] && job != thisjob)
-	dotrap(SIGCHLD);
+	dotrap(SIGCHLD, 0);
 
     /* When MONITOR is set, the foreground process runs in a different *
      * process group from the shell, so the shell will not receive     *
@@ -389,7 +389,7 @@ update_job(Job jn)
 
 	if (sig == SIGINT || sig == SIGQUIT) {
 	    if (sigtrapped[sig]) {
-		dotrap(sig);
+		dotrap(sig, 0);
 		/* We keep the errflag as set or not by dotrap.
 		 * This is to fulfil the promise to carry on
 		 * with the jobs if trap returns zero.
@@ -878,7 +878,9 @@ waitforpid(pid_t pid)
 	else
 	    kill(pid, SIGCONT);
 
-	child_suspend(SIGINT);
+	ALLOWTRAPS {
+	    child_suspend(SIGINT);
+	} DISALLOWTRAPS;
 	child_block();
     }
     child_unblock();
@@ -900,7 +902,9 @@ waitjob(int job, int sig)
 	while (!errflag && jn->stat &&
 	       !(jn->stat & STAT_DONE) &&
 	       !(interact && (jn->stat & STAT_STOPPED))) {
-	    child_suspend(sig);
+	    ALLOWTRAPS {
+		child_suspend(sig);
+	    } DISALLOWTRAPS;
 	    /* Commenting this out makes ^C-ing a job started by a function
 	       stop the whole function again.  But I guess it will stop
 	       something else from working properly, we have to find out
@@ -1363,7 +1367,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
 		killjb(jobtab + job, SIGCONT);
 	    }
 	    if (func == BIN_WAIT)
-	        waitjob(job, SIGINT);
+		waitjob(job, SIGINT);
 	    if (func != BIN_BG) {
 		waitjobs();
 		retval = lastval2;
diff --git a/Src/signals.c b/Src/signals.c
index b397e1047..693337dbd 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -497,7 +497,7 @@ handler(int sig)
  
     case SIGHUP:
         if (sigtrapped[SIGHUP])
-            dotrap(SIGHUP);
+            dotrap(SIGHUP, 0);
         else {
             stopmsg = 1;
             zexit(SIGHUP, 1);
@@ -506,7 +506,7 @@ handler(int sig)
  
     case SIGINT:
         if (sigtrapped[SIGINT])
-            dotrap(SIGINT);
+            dotrap(SIGINT, 0);
         else {
 	    if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
 		isset(INTERACTIVE) && noerrexit < 0)
@@ -523,14 +523,14 @@ handler(int sig)
     case SIGWINCH:
         adjustwinsize(1);  /* check window size and adjust */
 	if (sigtrapped[SIGWINCH])
-	    dotrap(SIGWINCH);
+	    dotrap(SIGWINCH, 0);
         break;
 #endif
 
     case SIGALRM:
         if (sigtrapped[SIGALRM]) {
 	    int tmout;
-            dotrap(SIGALRM);
+            dotrap(SIGALRM, 0);
 
 	    if ((tmout = getiparam("TMOUT")))
 		alarm(tmout);           /* reset the alarm */
@@ -549,7 +549,7 @@ handler(int sig)
         break;
  
     default:
-        dotrap(sig);
+        dotrap(sig, 0);
         break;
     }   /* end of switch(sig) */
  
@@ -907,7 +907,9 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
      * function will test for this, but this way we keep status flags *
      * intact without working too hard.  Special cases (e.g. calling  *
      * a trap for SIGINT after the error flag was set) are handled    *
-     * by the calling code.  (PWS 1995/06/08).			      */
+     * by the calling code.  (PWS 1995/06/08).			      *
+     *                                                                *
+     * This test is now replicated in dotrap().                       */
     if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
         return;
 
@@ -953,15 +955,67 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
 	    breaks = loops;
     }
 
+    /*
+     * If zle was running while the trap was executed, see if we
+     * need to restore the display.
+     */
+    if (zleactive && resetneeded)
+	zrefresh();
+
     if (*sigtr != ZSIG_IGNORED)
 	*sigtr &= ~ZSIG_IGNORED;
 }
 
-/* Standard call to execute a trap for a given signal */
+/* != 0 if trap handlers can be called immediately */
+
+/**/
+mod_export int trapsallowed;
+
+/* Queued traps and allocated length of queue. */
+
+static int *trapqueue, trapqlen;
+
+/* Number of used slots in trap queue. */
+
+/**/
+mod_export int trapqused;
+
+/* Standard call to execute a trap for a given signal.  The second
+ * argument should be zero if we may need to put the trap on the queue
+ * and 1 if it may be called immediately.  It should never be set to
+ * anything less than zero, that's used internally. */
 
 /**/
 void
-dotrap(int sig)
+dotrap(int sig, int now)
 {
-    dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    /* Copied from dotrapargs(). */
+    if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
+	return;
+
+    if (now || trapsallowed) {
+	if (now < 0)
+	    RUNTRAPS();
+	dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
+    } else {
+	if (trapqlen == trapqused)
+	    trapqueue = (int *) zrealloc(trapqueue, (trapqlen += 32));
+	trapqueue[trapqused++] = sig;
+    }
+}
+
+/**/
+mod_export void
+doqueuedtraps(void)
+{
+    int sig, ota = trapsallowed;
+
+    trapsallowed = 1;
+    while (trapqused) {
+	trapqused--;
+	sig = *trapqueue;
+	memcpy(trapqueue, trapqueue + 1, trapqused * sizeof(int));
+	dotrap(sig, -1);
+    }
+    trapsallowed = ota;
 }
diff --git a/Src/signals.h b/Src/signals.h
index b6485e6b3..45978dd1e 100644
--- a/Src/signals.h
+++ b/Src/signals.h
@@ -56,8 +56,8 @@
 # define sigismember(s,n)  ((*(s) & (1 << ((n) - 1))) != 0)
 #endif   /* ifndef POSIX_SIGNALS */
  
-#define child_block()      signal_block(signal_mask(SIGCHLD))
-#define child_unblock()    signal_unblock(signal_mask(SIGCHLD))
+#define child_block()      signal_block(sigchld_mask)
+#define child_unblock()    signal_unblock(sigchld_mask)
 #define child_suspend(S)   signal_suspend(SIGCHLD, S)
 
 /* ignore a signal */
@@ -92,3 +92,34 @@
 	} \
     } \
 } while (0)
+
+
+/* Make some signal functions faster. */
+
+#ifdef POSIX_SIGNALS
+#define signal_block(S) \
+    ((dummy_sigset1 = (S)), \
+     sigprocmask(SIG_BLOCK, &dummy_sigset1, &dummy_sigset2), \
+     dummy_sigset2)
+#else
+# ifdef BSD_SIGNALS
+#define signal_block(S) sigblock(S)
+# else
+extern sigset_t signal_block _((sigset_t));
+# endif  /* BSD_SIGNALS   */
+#endif   /* POSIX_SIGNALS */
+
+#ifdef POSIX_SIGNALS
+#define signal_unblock(S) \
+    ((dummy_sigset1 = (S)), \
+     sigprocmask(SIG_UNBLOCK, &dummy_sigset1, &dummy_sigset2), \
+     dummy_sigset2)
+#else
+extern sigset_t signal_unblock _((sigset_t));
+#endif   /* POSIX_SIGNALS */
+
+#define RUNTRAPS() do { if (trapqused) doqueuedtraps(); } while (0)
+#define ALLOWTRAPS do { RUNTRAPS(); trapsallowed++; do
+#define DISALLOWTRAPS while (0); RUNTRAPS(); trapsallowed--; } while (0)
+#define ALLOWTRAPS_RETURN(V) \
+    do { RUNTRAPS(); trapsallowed--; return (V); } while (0)
diff --git a/Src/utils.c b/Src/utils.c
index b7b8d1295..e61e84a03 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1418,12 +1418,38 @@ checkrmall(char *s)
 }
 
 /**/
+mod_export int
+ztrapread(int fd, char *buf, int len)
+{
+    int ret;
+
+    ALLOWTRAPS {
+	ret = read(fd, buf, len);
+    } DISALLOWTRAPS;
+
+    return ret;
+}
+
+/**/
+mod_export int
+ztrapwrite(int fd, char *buf, int len)
+{
+    int ret;
+
+    ALLOWTRAPS {
+	ret = write(fd, buf, len);
+    } DISALLOWTRAPS;
+
+    return ret;
+}
+
+/**/
 int
 read1char(void)
 {
     char c;
 
-    while (read(SHTTY, &c, 1) != 1) {
+    while (ztrapread(SHTTY, &c, 1) != 1) {
 	if (errno != EINTR || errflag || retflag || breaks || contflag)
 	    return -1;
     }
@@ -1440,7 +1466,7 @@ noquery(int purge)
     ioctl(SHTTY, FIONREAD, (char *)&val);
     if (purge) {
 	for (; val; val--)
-	    read(SHTTY, &c, 1);
+	    ztrapread(SHTTY, &c, 1);
     }
 #endif
 
diff --git a/Src/zsh.h b/Src/zsh.h
index cdf1ed489..c4642434b 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1627,8 +1627,6 @@ struct heap {
 #endif
 ;
 
-# define LASTALLOC_RETURN return
-
 # define NEWHEAPS(h)    do { Heap _switch_oldheaps = h = new_heaps(); do
 # define OLDHEAPS       while (0); old_heaps(_switch_oldheaps); } while (0);