about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2001-01-16 13:44:18 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2001-01-16 13:44:18 +0000
commit757168e2c8af374436108266cc3cfd32a946a590 (patch)
tree293929274f50de8733f00c4ae561a85e9c5fc16f
parent052316fea3b74599de04fb3990a444b0ba08b04b (diff)
downloadzsh-757168e2c8af374436108266cc3cfd32a946a590.tar.gz
zsh-757168e2c8af374436108266cc3cfd32a946a590.tar.xz
zsh-757168e2c8af374436108266cc3cfd32a946a590.zip
remove 13108 (trap queues); replace with signal queueing to ensure that user signal handlers are only executed when it is safe to run them (13365)
-rw-r--r--ChangeLog11
-rw-r--r--Src/Modules/zftp.c32
-rw-r--r--Src/Modules/zpty.c4
-rw-r--r--Src/Modules/zutil.c13
-rw-r--r--Src/Zle/compcore.c16
-rw-r--r--Src/Zle/complist.c11
-rw-r--r--Src/Zle/computil.c10
-rw-r--r--Src/Zle/zle_main.c35
-rw-r--r--Src/Zle/zle_tricky.c19
-rw-r--r--Src/builtin.c126
-rw-r--r--Src/exec.c23
-rw-r--r--Src/glob.c19
-rw-r--r--Src/hashtable.c3
-rw-r--r--Src/hist.c28
-rw-r--r--Src/init.c4
-rw-r--r--Src/input.c4
-rw-r--r--Src/jobs.c27
-rw-r--r--Src/math.c2
-rw-r--r--Src/mem.c59
-rw-r--r--Src/module.c53
-rw-r--r--Src/params.c50
-rw-r--r--Src/parse.c60
-rw-r--r--Src/prompt.c4
-rw-r--r--Src/signals.c78
-rw-r--r--Src/signals.h40
-rw-r--r--Src/subst.c14
-rw-r--r--Src/utils.c58
-rw-r--r--Src/watch.c9
28 files changed, 546 insertions, 266 deletions
diff --git a/ChangeLog b/ChangeLog
index be44b1a64..3ad62c8a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2001-01-16  Sven Wischnowsky  <wischnow@zsh.org>
 
+	* 13365: Src/builtin.c, Src/exec.c, Src/glob.c, Src/hashtable.c,
+ 	Src/hist.c, Src/init.c, Src/input.c, Src/jobs.c, Src/math.c,
+ 	Src/mem.c, Src/module.c, Src/params.c, Src/parse.c, Src/prompt.c,
+ 	Src/signals.c, Src/signals.h, Src/subst.c, Src/utils.c,
+ 	Src/watch.c, Src/Modules/zftp.c, Src/Modules/zpty.c,
+ 	Src/Modules/zutil.c, Src/Zle/compcore.c, Src/Zle/complist.c,
+ 	Src/Zle/computil.c, Src/Zle/zle_main.c, Src/Zle/zle_tricky.c:
+ 	remove 13108 (trap queues); replace with signal queueing to ensure
+ 	that user signal handlers are only executed when it is safe to run
+ 	them
+	
 	* 13364: Src/Zle/compctl.c: fix for ol' compctl when completing
  	hash keys
 	
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 5813a9144..9bcc65fa2 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;
-		ztrapwrite(zfsess->cfd, cmdbuf, 3);
+		write(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;
-		ztrapwrite(zfsess->cfd, cmdbuf, 3);
+		write(zfsess->cfd, cmdbuf, 3);
 		continue;
 
 	    case EOF:
@@ -863,8 +863,6 @@ zfgetmsg(void)
 
     if (zfsess->cfd == -1)
 	return 6;
-    if (!(verbose = getsparam("ZFTP_VERBOSE")))
-	verbose = "";
     zsfree(lastmsg);
     lastmsg = NULL;
 
@@ -890,6 +888,9 @@ zfgetmsg(void)
     zfsetparam("ZFTP_CODE", ztrdup(lastcodestr), ZFPM_READONLY);
     stopit = (*ptr++ != '-');
 
+    queue_signals();
+    if (!(verbose = getsparam("ZFTP_VERBOSE")))
+	verbose = "";
     if (strchr(verbose, lastcodestr[0])) {
 	/* print the whole thing verbatim */
 	printing = 1;
@@ -899,6 +900,7 @@ zfgetmsg(void)
 	printing = 2;
 	fputs(ptr, stderr);
     }
+    unqueue_signals();
     if (printing)
 	fputc('\n', stderr);
 
@@ -996,7 +998,7 @@ zfsendcmd(char *cmd)
 	return 6;
     }
     zfalarm(tmout);
-    ret = ztrapwrite(zfsess->cfd, cmd, strlen(cmd));
+    ret = write(zfsess->cfd, cmd, strlen(cmd));
     alarm(0);
 
     if (ret <= 0) {
@@ -1470,7 +1472,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
     int ret;
 
     if (!tmout)
-	return ztrapread(fd, bf, sz);
+	return read(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1479,7 +1481,7 @@ zfread(int fd, char *bf, off_t sz, int tmout)
     }
     zfalarm(tmout);
 
-    ret = ztrapread(fd, bf, sz);
+    ret = read(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -1495,7 +1497,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
     int ret;
 
     if (!tmout)
-	return ztrapwrite(fd, bf, sz);
+	return write(fd, bf, sz);
 
     if (setjmp(zfalrmbuf)) {
 	alarm(0);
@@ -1504,7 +1506,7 @@ zfwrite(int fd, char *bf, off_t sz, int tmout)
     }
     zfalarm(tmout);
 
-    ret = ztrapwrite(fd, bf, sz);
+    ret = write(fd, bf, sz);
 
     /* we don't bother turning off the whole alarm mechanism here */
     alarm(0);
@@ -1894,10 +1896,12 @@ zftp_open(char *name, char **args, int flags)
     if (setjmp(zfalrmbuf)) {
 	char *hname;
 	alarm(0);
+	queue_signals();
 	if ((hname = getsparam("ZFTP_HOST")) && *hname) 
 	    zwarnnam(name, "timeout connecting to %s", hname, 0);
 	else
 	    zwarnnam(name, "timeout on host name lookup", NULL, 0);
+	unqueue_signals();
 	zfclose(0);
 	return 1;
     }
@@ -2846,7 +2850,7 @@ zfclose(int leaveparams)
 	if (!zfnopen) {
 	    /* Write the final status in case this is a subshell */
 	    lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	    ztrapwrite(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
+	    write(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
 
 	    close(zfstatfd);
 	    zfstatfd = -1;
@@ -2933,10 +2937,12 @@ savesession()
     for (ps = zfparams, pd = zfsess->params; *ps; ps++, pd++) {
 	if (*pd)
 	    zsfree(*pd);
+	queue_signals();
 	if ((val = getsparam(*ps)))
 	    *pd = ztrdup(val);
 	else
 	    *pd = NULL;
+	unqueue_signals();
     }
     *pd = NULL;
 }
@@ -3123,7 +3129,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);
-	ztrapread(zfstatfd, (char *)zfstatusp, sizeof(int)*zfsesscnt);
+	read(zfstatfd, (char *)zfstatusp, sizeof(int)*zfsesscnt);
 	if (zfsess->cfd != -1 && (zfstatusp[zfsessno] & ZFST_CLOS)) {
 	    /* got closed in subshell without us knowing */
 	    zcfinish = 2;
@@ -3166,6 +3172,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
 	return 1;
     }
 
+    queue_signals();
     if ((prefs = getsparam("ZFTP_PREFS"))) {
 	zfprefs = 0;
 	for (ptr = prefs; *ptr; ptr++) {
@@ -3196,6 +3203,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
 	    }
 	}
     }
+    unqueue_signals();
 
     ret = (*zptr->fun)(fullname, args, zptr->flags);
 
@@ -3212,7 +3220,7 @@ bin_zftp(char *name, char **args, char *ops, int func)
 	 * but only for the active session.
 	 */
 	lseek(zfstatfd, zfsessno*sizeof(int), 0);
-	ztrapwrite(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
+	write(zfstatfd, (char *)zfstatusp+zfsessno, sizeof(int));
     }
     return ret;
 }
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index 297833a79..f96ffa0e3 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -539,7 +539,7 @@ ptywritestr(Ptycmd cmd, char *s, int len)
 
     for (; !errflag && !breaks && !retflag && !contflag && len;
 	 len -= written, s += written) {
-	if ((written = ztrapwrite(cmd->fd, s, len)) < 0 && cmd->nblock &&
+	if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock &&
 #ifdef EWOULDBLOCK
 	    errno == EWOULDBLOCK
 #else
@@ -583,7 +583,7 @@ ptywrite(Ptycmd cmd, char **args, int nonl)
 	int n;
 	char buf[BUFSIZ];
 
-	while ((n = ztrapread(0, buf, BUFSIZ)) > 0)
+	while ((n = read(0, buf, BUFSIZ)) > 0)
 	    if (ptywritestr(cmd, buf, n))
 		return 1;
     }
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 9dae030df..8a69a561b 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -219,12 +219,14 @@ evalstyle(Stypat p)
     }
     errflag = ef;
 
+    queue_signals();
     if ((ret = getaparam("reply")))
 	ret = arrdup(ret);
     else if ((str = getsparam("reply"))) {
 	ret = (char **) hcalloc(2 * sizeof(char *));
 	ret[0] = dupstring(str);
     }
+    unqueue_signals();
     unsetparam("reply");
 
     return ret;
@@ -725,12 +727,14 @@ savematch(MatchData *m)
 {
     char **a;
 
+    queue_signals();
     a = getaparam("match");
     m->match = a ? zarrdup(a) : NULL;
     a = getaparam("mbegin");
     m->mbegin = a ? zarrdup(a) : NULL;
     a = getaparam("mend");
     m->mend = a ? zarrdup(a) : NULL;
+    unqueue_signals();
 }
 
 static void
@@ -1078,8 +1082,13 @@ rmatch(RParseResult *sm, char *subj, char *var1, char *var2, int comp)
 	    if (next->pattern && pattry(next->patprog, subj) &&
 		(!next->guard || (execstring(next->guard, 1, 0), !lastval))) {
 		LinkNode aln;
-		char **mend = getaparam("mend");
-		int len = atoi(mend[0]);
+		char **mend;
+		int len;
+
+		queue_signals();
+		mend = getaparam("mend");
+		len = atoi(mend[0]);
+		unqueue_signals();
 
 		for (i = len; i; i--)
 		  if (*subj++ == Meta)
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 06e7afbfb..a7ada2564 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1526,14 +1526,15 @@ get_user_var(char *nam)
 	/* Otherwise it should be a parameter name. */
 	char **arr = NULL, *val;
 
+	queue_signals();
 	if ((arr = getaparam(nam)) || (arr = gethparam(nam)))
-	    return (incompfunc ? arrdup(arr) : arr);
-
-	if ((val = getsparam(nam))) {
+	    arr = (incompfunc ? arrdup(arr) : arr);
+	else if ((val = getsparam(nam))) {
 	    arr = (char **) zhalloc(2*sizeof(char *));
 	    arr[0] = (incompfunc ? dupstring(val) : val);
 	    arr[1] = NULL;
 	}
+	unqueue_signals();
 	return arr;
     }
 }
@@ -1542,14 +1543,19 @@ static char **
 get_data_arr(char *name, int keys)
 {
     struct value vbuf;
+    char **ret;
     Value v;
 
+    queue_signals();
     if (!(v = fetchvalue(&vbuf, &name, 1,
 			 (keys ? SCANPM_WANTKEYS : SCANPM_WANTVALS) |
 			 SCANPM_MATCHMANY)))
-	return NULL;
+	ret = NULL;
+    else
+	ret = getarrvalue(v);
+    unqueue_signals();
 
-    return getarrvalue(v);
+    return ret;
 }
 
 /* This is used by compadd to add a couple of matches. The arguments are
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 6982dc774..714719d62 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -340,6 +340,7 @@ getcols(Listcols c)
     int i, l;
 
     max_caplen = lr_caplen = 0;
+    queue_signals();
     if (!(s = getsparam("ZLS_COLORS")) &&
 	!(s = getsparam("ZLS_COLOURS"))) {
 	for (i = 0; i < NUM_COLS; i++)
@@ -356,6 +357,7 @@ getcols(Listcols c)
 	if ((max_caplen = strlen(c->files[COL_MA]->col)) <
 	    (l = strlen(c->files[COL_EC]->col)))
 	    max_caplen = l;
+	unqueue_signals();
 	return;
     }
     /* We have one of the parameters, use it. */
@@ -366,6 +368,7 @@ getcols(Listcols c)
 	    s++;
 	else
 	    s = getcoldef(c, s);
+    unqueue_signals();
 
     /* Use default values for those that aren't set explicitly. */
     for (i = 0; i < NUM_COLS; i++) {
@@ -1528,8 +1531,10 @@ complistmatches(Hookdef dummy, Chdata dat)
     mscroll = 0;
     mlistp = NULL;
 
+    queue_signals();
     if (mselect >= 0 || mlbeg >= 0 ||
-	(mlistp = getsparam("LISTPROMPT"))) {
+	(mlistp = dupstring(getsparam("LISTPROMPT")))) {
+	unqueue_signals();
 	if (mlistp && !*mlistp)
 	    mlistp = "%SAt %p: Hit TAB for more, or the character to insert%s";
 	trashzle();
@@ -1545,6 +1550,7 @@ complistmatches(Hookdef dummy, Chdata dat)
 	    minfo.asked = (listdat.nlines + nlnct <= lines);
 	}
     } else {
+	unqueue_signals();
 	mlistp = NULL;
 	if (asklist()) {
 	    amatches = oamatches;
@@ -1641,6 +1647,7 @@ domenuselect(Hookdef dummy, Chdata dat)
     int nolist = 0;
     char *s;
 
+    queue_signals();
     if (fdat || (dummy && (!(s = getsparam("MENUSELECT")) ||
 			   (dat && dat->num < atoi(s))))) {
 	if (fdat) {
@@ -1648,6 +1655,7 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    fdat->num = dat->num;
 	    fdat->nmesg = dat->nmesg;
 	}
+	unqueue_signals();
 	return 0;
     }
     if ((s = getsparam("MENUSCROLL"))) {
@@ -1659,6 +1667,7 @@ domenuselect(Hookdef dummy, Chdata dat)
     }
     if ((mstatus = dupstring(getsparam("MENUPROMPT"))) && !*mstatus)
 	mstatus = "%SScrolling active: current selection at %p%s";
+    unqueue_signals();
     mhasstat = (mstatus && *mstatus);
     fdat = dat;
     selectlocalmap(mskeymap);
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 3672de687..4afc492dc 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -2606,6 +2606,7 @@ bin_compquote(char *nam, char **args, char *ops, int func)
 
     while ((name = *args++)) {
 	name = dupstring(name);
+	queue_signals();
 	if ((v = getvalue(&vbuf, &name, 0))) {
 	    switch (PM_TYPE(v->pm->flags)) {
 	    case PM_SCALAR:
@@ -2630,6 +2631,7 @@ bin_compquote(char *nam, char **args, char *ops, int func)
 	    }
 	} else
 	    zwarnnam(nam, "unknown parameter: %s", args[-1], 0);
+	unqueue_signals();
     }
     return 0;
 }
@@ -3580,6 +3582,7 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
 		zwarnnam(nam, "too few arguments", NULL, 0);
 		return 1;
 	    }
+	    queue_signals();
 	    if (!(tmp = getaparam(args[1]))) {
 		zwarnnam(nam, "unknown parameter: %s", args[1], 0);
 		return 0;
@@ -3590,6 +3593,7 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
 					    l, getaparam(args[2]), args[3],
 					    args[4], args[5],
 					    getaparam(args[6]), args + 7));
+	    unqueue_signals();
 	    return 0;
 	}
     case 'i':
@@ -3608,16 +3612,19 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
 		zwarnnam(nam, "too many arguments", NULL, 0);
 		return 1;
 	    }
+	    queue_signals();
 	    tmp = getaparam(args[2]);
 	    l = newlinklist();
 	    if (tmp)
 		for (; *tmp; tmp++)
 		    addlinknode(l, *tmp);
 	    if (!(tmp = getaparam(args[1]))) {
+		unqueue_signals();
 		zwarnnam(nam, "unknown parameter: %s", args[1], 0);
 		return 0;
 	    }
 	    cf_ignore(tmp, l, args[3], args[4]);
+	    unqueue_signals();
 	    set_list_array(args[2], l);
 	    return 0;
 	}
@@ -3635,12 +3642,15 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
 		zwarnnam(nam, "too many arguments", NULL, 0);
 		return 1;
 	    }
+	    queue_signals();
 	    if (!(tmp = getaparam(args[1]))) {
+		unqueue_signals();
 		zwarnnam(nam, "unknown parameter: %s", args[1], 0);
 		return 0;
 	    }
 	    if ((l = cf_remove_other(tmp, args[2], &ret)))
 		set_list_array(args[1], l);
+	    unqueue_signals();
 	    return ret;
 	}
     }
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index b2a662072..c5923d74d 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -313,17 +313,12 @@ static int
 breakread(int fd, char *buf, int n)
 {
     fd_set f;
-    int ret;
 
     FD_ZERO(&f);
     FD_SET(fd, &f);
 
-    ALLOWTRAPS {
-	ret = (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
-	       EOF : read(fd, buf, n));
-    } DISALLOWTRAPS;
-
-    return ret;
+    return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
+	    EOF : read(fd, buf, n));
 }
 
 # define read    breakread
@@ -394,7 +389,7 @@ getkey(int keytmout)
 #  else
 	    ioctl(SHTTY, TCSETA, &ti.tio);
 #  endif
-	    r = ztrapread(SHTTY, &cc, 1);
+	    r = read(SHTTY, &cc, 1);
 #  ifdef HAVE_TERMIOS_H
 	    tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
 #  else
@@ -405,7 +400,7 @@ getkey(int keytmout)
 #endif
 	}
 	for (;;) {
-	    r = ztrapread(SHTTY, &cc, 1);
+	    r = read(SHTTY, &cc, 1);
 	    if (r == 1)
 		break;
 	    if (r == 0) {
@@ -664,8 +659,11 @@ execzlefunc(Thingy func, char **args)
 		ret = completecall(args);
 		if (atcurhist)
 		    histline = curhist;
-	    } else
+	    } else {
+		queue_signals();
 		ret = w->u.fn(args);
+		unqueue_signals();
+	    }
 	    if (!(wflags & ZLE_NOTCOMMAND))
 		lastcmd = wflags;
 	}
@@ -836,9 +834,11 @@ bin_vared(char *name, char **args, char *ops, int func)
     }
     /* handle non-existent parameter */
     s = args[0];
+    queue_signals();
     v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR),
 		   SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
     if (!v && !create) {
+	unqueue_signals();
 	zwarnnam(name, "no such variable: %s", args[0], 0);
 	return 1;
     } else if (v) {
@@ -885,11 +885,13 @@ bin_vared(char *name, char **args, char *ops, int func)
 	} else {
 	    s = ztrdup(getstrvalue(v));
 	}
-	pm = v->pm;
+	unqueue_signals();
     } else if (*s) {
+	unqueue_signals();
 	zwarnnam(name, "invalid parameter name: %s", args[0], 0);
 	return 1;
     } else {
+	unqueue_signals();
 	s = ztrdup(s);
     }
 
@@ -935,14 +937,12 @@ bin_vared(char *name, char **args, char *ops, int func)
     if (t[strlen(t) - 1] == '\n')
 	t[strlen(t) - 1] = '\0';
     /* final assignment of parameter value */
-    if (create && (!pm || (type && PM_TYPE(pm->flags) != type))) {
-	if (pm)
-	    unsetparam(args[0]);
+    if (create) {
+	unsetparam(args[0]);
 	createparam(args[0], type);
-	pm = 0;
     }
-    if (!pm)
-	pm = (Param) paramtab->getnode(paramtab, args[0]);
+    queue_signals();
+    pm = (Param) paramtab->getnode(paramtab, args[0]);
     if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
 	char **a;
 
@@ -957,6 +957,7 @@ bin_vared(char *name, char **args, char *ops, int func)
 	    sethparam(args[0], a);
     } else
 	setsparam(args[0], t);
+    unqueue_signals();
     return 0;
 }
 
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index d6250ce23..7476b833b 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -535,24 +535,33 @@ parambeg(char *s)
 static int
 docomplete(int lst)
 {
+    static int active = 0;
+
     char *s, *ol;
     int olst = lst, chl = 0, ne = noerrs, ocs, ret = 0, dat[2];
 
+    if (active) {
+	zwarn("completion cannot be used recursively (yet)", NULL, 0);
+	return 1;
+    }
+    active = 1;
     if (undoing)
 	setlastline();
 
     if (!module_loaded("zsh/complete"))
 	load_module("zsh/compctl");
 
-    if (runhookdef(BEFORECOMPLETEHOOK, (void *) &lst))
+    if (runhookdef(BEFORECOMPLETEHOOK, (void *) &lst)) {
+	active = 0;
 	return 0;
-
+    }
     /* Expand history references before starting completion.  If anything *
      * changed, do no more.                                               */
 
-    if (doexpandhist())
+    if (doexpandhist()) {
+	active = 0;
 	return 0;
-
+    }
     metafy_line();
 
     ocs = cs;
@@ -608,6 +617,7 @@ docomplete(int lst)
 	    unmetafy_line();
 	    zsfree(s);
 	    zsfree(qword);
+	    active = 0;
 	    return 1;
 	}
 	ocs = cs;
@@ -785,6 +795,7 @@ docomplete(int lst)
     dat[1] = ret;
     runhookdef(AFTERCOMPLETEHOOK, (void *) dat);
 
+    active = 0;
     return dat[1];
 }
 
diff --git a/Src/builtin.c b/Src/builtin.c
index 16e5caca7..1d54804d1 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -407,7 +407,9 @@ bin_enable(char *name, char **argv, char *ops, int func)
      * print nodes NOT containing the DISABLED flag, else scanhashtable will *
      * print nodes containing the DISABLED flag.                             */
     if (!*argv) {
+	queue_signals();
 	scanhashtable(ht, 1, flags1, flags2, ht->printnode, 0);
+	unqueue_signals();
 	return 0;
     }
 
@@ -416,8 +418,11 @@ bin_enable(char *name, char **argv, char *ops, int func)
 	for (; *argv; argv++) {
 	    /* parse pattern */
 	    tokenize(*argv);
-	    if ((pprog = patcompile(*argv, PAT_STATIC, 0)))
+	    if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
+		queue_signals();
 		match += scanmatchtable(ht, pprog, 0, 0, scanfunc, 0);
+		unqueue_signals();
+	    }
 	    else {
 		untokenize(*argv);
 		zwarnnam(name, "bad pattern : %s", *argv, 0);
@@ -431,6 +436,7 @@ bin_enable(char *name, char **argv, char *ops, int func)
     }
 
     /* Take arguments literally -- do not glob */
+    queue_signals();
     for (; *argv; argv++) {
 	    if ((hn = ht->getnode2(ht, *argv))) {
 		scanfunc(hn, 0);
@@ -439,6 +445,7 @@ bin_enable(char *name, char **argv, char *ops, int func)
 		returnval = 1;
 	    }
 	}
+    unqueue_signals();
     return returnval;
 }
 
@@ -511,6 +518,7 @@ bin_set(char *nam, char **args, char *ops, int func)
     inittyptab();
 
     /* Show the parameters, possibly with values */
+    queue_signals();
     if (!hadopt && !*args)
 	scanhashtable(paramtab, 1, 0, 0, paramtab->printnode,
 	    hadplus ? PRINT_NAMEONLY : 0);
@@ -520,8 +528,10 @@ bin_set(char *nam, char **args, char *ops, int func)
 	scanhashtable(paramtab, 1, PM_ARRAY, 0, paramtab->printnode,
 	    hadplus ? PRINT_NAMEONLY : 0);
     }
-    if (!*args && !hadend)
+    if (!*args && !hadend) {
+	unqueue_signals();
 	return 0;
+    }
     if (array)
 	args++;
     if (sort)
@@ -550,6 +560,7 @@ bin_set(char *nam, char **args, char *ops, int func)
 	freearray(pparams);
 	pparams = zarrdup(args);
     }
+    unqueue_signals();
     return 0;
 }
 
@@ -588,6 +599,7 @@ bin_dirs(char *name, char **argv, char *ops, int func)
 
     /* with the -v option, provide a numbered list of directories, starting at
     zero */
+    queue_signals();
     if (ops['v']) {
 	LinkNode node;
 	int pos = 1;
@@ -599,11 +611,13 @@ bin_dirs(char *name, char **argv, char *ops, int func)
 	    fprintdir(getdata(node), stdout);
 	}
 	putchar('\n');
+	unqueue_signals();
 	return 0;
     }
     /* given no arguments, list the stack normally */
     if (!*argv) {
 	printdirstack();
+	unqueue_signals();
 	return 0;
     }
     /* replace the stack with the specified directories */
@@ -614,6 +628,7 @@ bin_dirs(char *name, char **argv, char *ops, int func)
 	freelinklist(dirstack, freestr);
 	dirstack = l;
     }
+    unqueue_signals();
     return 0;
 }
 
@@ -693,9 +708,11 @@ bin_cd(char *nam, char **argv, char *ops, int func)
     }
   brk:
     chasinglinks = ops['P'] || (isset(CHASELINKS) && !ops['L']);
+    queue_signals();
     zpushnode(dirstack, ztrdup(pwd));
     if (!(dir = cd_get_dest(nam, argv, ops, func))) {
 	zsfree(getlinknode(dirstack));
+	unqueue_signals();
 	return 1;
     }
     cd_new_pwd(func, dir);
@@ -715,6 +732,7 @@ bin_cd(char *nam, char **argv, char *ops, int func)
 	    chdir(unmeta(pwd));
 	}
     }
+    unqueue_signals();
     return 0;
 }
 
@@ -1192,19 +1210,23 @@ bin_fc(char *nam, char **argv, char *ops, int func)
 	    return 1;
 	}
     }
+    queue_signals();
     if (ops['R']) {
 	/* read history from a file */
 	readhistfile(*argv, 1, ops['I'] ? HFILE_SKIPOLD : 0);
+	unqueue_signals();
 	return 0;
     }
     if (ops['W']) {
 	/* write history to a file */
 	savehistfile(*argv, 1, ops['I'] ? HFILE_SKIPOLD : 0);
+	unqueue_signals();
 	return 0;
     }
     if (ops['A']) {
 	/* append history to a file */
 	savehistfile(*argv, 1, HFILE_APPEND | (ops['I'] ? HFILE_SKIPOLD : 0));
+	unqueue_signals();
 	return 0;
     }
     /* put foo=bar type arguments into the substitution list */
@@ -1226,20 +1248,25 @@ bin_fc(char *nam, char **argv, char *ops, int func)
     if (*argv) {
 	minflag = **argv == '-';
 	first = fcgetcomm(*argv);
-	if (first == -1)
+	if (first == -1) {
+	    unqueue_signals();
 	    return 1;
+	}
 	argv++;
     }
     /* interpret and check second history line specifier */
     if (*argv) {
 	last = fcgetcomm(*argv);
-	if (last == -1)
+	if (last == -1) {
+	    unqueue_signals();
 	    return 1;
+	}
 	argv++;
     }
     /* There is a maximum of two history specifiers.  At least, there *
      * will be as long as the history list is one-dimensional.        */
     if (*argv) {
+	unqueue_signals();
 	zwarnnam("fc", "too many arguments", NULL, 0);
 	return 1;
     }
@@ -1256,11 +1283,13 @@ bin_fc(char *nam, char **argv, char *ops, int func)
 	last = (minflag) ? curhist : first;
     else if (last < first)
 	last = first;
-    if (ops['l'])
+    if (ops['l']) {
 	/* list the required part of the history */
 	retval = fclist(stdout, !ops['n'], ops['r'], ops['D'],
 			ops['d'] + ops['f'] * 2 + ops['E'] * 4 + ops['i'] * 8,
 			first, last, asgf, pprog);
+	unqueue_signals();
+    }
     else {
 	/* edit history file, and (if successful) use the result as a new command */
 	int tempfd;
@@ -1272,6 +1301,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
 	if (((tempfd = open(fil, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0600))
 	    == -1) ||
 		((out = fdopen(tempfd, "w")) == NULL)) {
+	    unqueue_signals();
 	    zwarnnam("fc", "can't open temp file: %e", NULL, errno);
 	} else {
 	    if (!fclist(out, 0, ops['r'], 0, 0, first, last, asgf, pprog)) {
@@ -1281,6 +1311,7 @@ bin_fc(char *nam, char **argv, char *ops, int func)
 		if (!editor)
 		    editor = DEFAULT_FCEDIT;
 
+		unqueue_signals();
 		if (fcedit(editor, fil)) {
 		    if (stuff(fil))
 			zwarnnam("fc", "%e: %s", s, errno);
@@ -1289,7 +1320,8 @@ bin_fc(char *nam, char **argv, char *ops, int func)
 			retval = lastval;
 		    }
 		}
-	    }
+	    } else
+		unqueue_signals();
 	}
 	unlink(fil);
     }
@@ -1847,6 +1879,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 
     on &= ~off;
 
+    queue_signals();
+
     /* Given no arguments, list whatever the options specify. */
     if (!*argv) {
 	if (!(on|roff))
@@ -1854,6 +1888,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	if (roff || ops['+'])
 	    printflags |= PRINT_NAMEONLY;
 	scanhashtable(paramtab, 1, on|roff, 0, paramtab->printnode, printflags);
+	unqueue_signals();
 	return 0;
     }
 
@@ -1868,20 +1903,27 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 
 	if (ops['m']) {
 	    zwarnnam(name, "incompatible options for -T", NULL, 0);
+	    unqueue_signals();
 	    return 1;
 	}
 	on &= ~off;
 	if (!argv[1] || argv[2]) {
 	    zwarnnam(name, "-T requires names of scalar and array", NULL, 0);
+	    unqueue_signals();
 	    return 1;
 	}
 
-	if (!(asg = getasg(argv[0])))
+	if (!(asg = getasg(argv[0]))) {
+	    unqueue_signals();
 	    return 1;
+	}
 	asg0 = *asg;
-	if (!(asg = getasg(argv[1])))
+	if (!(asg = getasg(argv[1]))) {
+	    unqueue_signals();
 	    return 1;
+	}
 	if (!strcmp(asg0.name, asg->name)) {
+	    unqueue_signals();
 	    zerrnam(name, "can't tie a variable to itself", NULL, 0);
 	    return 1;
 	}
@@ -1910,9 +1952,10 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 				 (Param)paramtab->getnode(paramtab,
 							  asg->name),
 				 func, (on | PM_ARRAY) & ~PM_EXPORTED,
-				 off, roff, asg->value, NULL)))
+				 off, roff, asg->value, NULL))) {
+	    unqueue_signals();
 	    return 1;
-
+	}
 	/*
 	 * Create the tied colonarray.  We make it as a normal scalar
 	 * and fix up the oddities later.
@@ -1924,6 +1967,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	    if (oldval)
 		zsfree(oldval);
 	    unsetparam_pm(apm, 1, 1);
+	    unqueue_signals();
 	    return 1;
 	}
 
@@ -1931,6 +1975,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	apm->ename = ztrdup(asg0.name);
 	if (oldval)
 	    setsparam(asg0.name, oldval);
+	unqueue_signals();
 
 	return 0;
     }
@@ -1987,6 +2032,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 		    returnval = 1;
 	    }
 	}
+	unqueue_signals();
 	return returnval;
     }
 
@@ -2005,6 +2051,7 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 			    func, on, off, roff, asg->value, NULL))
 	    returnval = 1;
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2074,6 +2121,9 @@ bin_functions(char *name, char **argv, char *ops, int func)
      * are given, we will print only functions containing these  *
      * flags, else we'll print them all.                         */
     if (!*argv) {
+	int ret = 0;
+
+	queue_signals();
 	if (ops['X'] == 1) {
 	    if ((shf = (Shfunc) shfunctab->getnode(shfunctab, scriptname))) {
 		DPUTS(!shf->funcdef,
@@ -2083,14 +2133,15 @@ bin_functions(char *name, char **argv, char *ops, int func)
 		shfunctab->addnode(shfunctab, ztrdup(scriptname), shf);
 	    }
 	    shf->flags = on;
-	    return eval_autoload(shf, scriptname, ops, func);
+	    ret = eval_autoload(shf, scriptname, ops, func);
 	} else {
 	    if (ops['U'] && !ops['u'])
 		on &= ~PM_UNDEFINED;
 	    scanhashtable(shfunctab, 1, on|off, DISABLED, shfunctab->printnode,
 			  pflags);
 	}
-	return 0;
+	unqueue_signals();
+	return ret;
     }
 
     /* With the -m option, treat arguments as glob patterns */
@@ -2101,6 +2152,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 	    tokenize(*argv);
 	    if ((pprog = patcompile(*argv, PAT_STATIC, 0))) {
 		/* with no options, just print all functions matching the glob pattern */
+		queue_signals();
 		if (!(on|off)) {
 		    scanmatchtable(shfunctab, pprog, 0, DISABLED,
 				   shfunctab->printnode, pflags);
@@ -2120,6 +2172,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 			    }
 		    }
 		}
+		unqueue_signals();
 	    } else {
 		untokenize(*argv);
 		zwarnnam(name, "bad pattern : %s", *argv, 0);
@@ -2130,6 +2183,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
     }
 
     /* Take the arguments literally -- do not glob */
+    queue_signals();
     for (; *argv; argv++) {
 	if (ops['w'])
 	    returnval = dump_autoload(name, *argv, on, ops, func);
@@ -2155,6 +2209,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 	} else
 	    returnval = 1;
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2206,6 +2261,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
 	    tokenize(s);
 	    if ((pprog = patcompile(s, PAT_STATIC, NULL))) {
 		/* Go through the parameter table, and unset any matches */
+		queue_signals();
 		for (i = 0; i < paramtab->hsize; i++) {
 		    for (pm = (Param) paramtab->nodes[i]; pm; pm = next) {
 			/* record pointer to next, since we may free this one */
@@ -2218,6 +2274,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
 			}
 		    }
 		}
+		unqueue_signals();
 	    } else {
 		untokenize(s);
 		zwarnnam(name, "bad pattern : %s", s, 0);
@@ -2231,6 +2288,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
     }
 
     /* do not glob -- unset the given parameter */
+    queue_signals();
     while ((s = *argv++)) {
 	char *ss = strchr(s, '[');
 	char *sse = ss;
@@ -2268,6 +2326,7 @@ bin_unset(char *name, char **argv, char *ops, int func)
 	if (ss)
 	    *ss = '[';
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2313,6 +2372,7 @@ bin_whence(char *nam, char **argv, char *ops, int func)
 		returnval = 1;
 		continue;
 	    }
+	    queue_signals();
 	    if (!ops['p']) {
 		/* -p option is for path search only.    *
 		 * We're not using it, so search for ... */
@@ -2339,11 +2399,13 @@ bin_whence(char *nam, char **argv, char *ops, int func)
 	    scanmatchtable(cmdnamtab, pprog, 0, 0,
 			   cmdnamtab->printnode, printflags);
 
+	    unqueue_signals();
 	}
-    return returnval;
+	return returnval;
     }
 
     /* Take arguments literally -- do not glob */
+    queue_signals();
     for (; *argv; argv++) {
 	informed = 0;
 
@@ -2436,6 +2498,7 @@ bin_whence(char *nam, char **argv, char *ops, int func)
 	    returnval = 1;
 	}
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2496,10 +2559,13 @@ bin_hash(char *name, char **argv, char *ops, int func)
 
     /* Given no arguments, display current hash table. */
     if (!*argv) {
+	queue_signals();
 	scanhashtable(ht, 1, 0, 0, ht->printnode, printflags);
+	unqueue_signals();
 	return 0;
     }
 
+    queue_signals();
     while (*argv) {
 	void *hn;
 	if (ops['m']) {
@@ -2553,6 +2619,7 @@ bin_hash(char *name, char **argv, char *ops, int func)
 	    ht->printnode(hn, 0);
 	argv++;
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2586,6 +2653,7 @@ bin_unhash(char *name, char **argv, char *ops, int func)
 	    tokenize(*argv);
 	    if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
 		/* remove all nodes matching glob pattern */
+		queue_signals();
 		for (i = 0; i < ht->hsize; i++) {
 		    for (hn = ht->nodes[i]; hn; hn = nhn) {
 			/* record pointer to next, since we may free this one */
@@ -2596,6 +2664,7 @@ bin_unhash(char *name, char **argv, char *ops, int func)
 			}
 		    }
 		}
+		unqueue_signals();
 	    } else {
 		untokenize(*argv);
 		zwarnnam(name, "bad pattern : %s", *argv, 0);
@@ -2609,6 +2678,7 @@ bin_unhash(char *name, char **argv, char *ops, int func)
     }
 
     /* Take arguments literally -- do not glob */
+    queue_signals();
     for (; *argv; argv++) {
 	if ((hn = ht->removenode(ht, *argv))) {
 	    ht->freenode(hn);
@@ -2617,6 +2687,7 @@ bin_unhash(char *name, char **argv, char *ops, int func)
 	    returnval = 1;
 	}
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2656,7 +2727,9 @@ bin_alias(char *name, char **argv, char *ops, int func)
     /* In the absence of arguments, list all aliases.  If a command *
      * line flag is specified, list only those of that type.        */
     if (!*argv) {
+	queue_signals();
 	scanhashtable(aliastab, 1, flags1, flags2, aliastab->printnode, printflags);
+	unqueue_signals();
 	return 0;
     }
 
@@ -2667,8 +2740,10 @@ bin_alias(char *name, char **argv, char *ops, int func)
 	    tokenize(*argv);  /* expand argument */
 	    if ((pprog = patcompile(*argv, PAT_STATIC, NULL))) {
 		/* display the matching aliases */
+		queue_signals();
 		scanmatchtable(aliastab, pprog, flags1, flags2,
 			       aliastab->printnode, printflags);
+		unqueue_signals();
 	    } else {
 		untokenize(*argv);
 		zwarnnam(name, "bad pattern : %s", *argv, 0);
@@ -2679,6 +2754,7 @@ bin_alias(char *name, char **argv, char *ops, int func)
     }
 
     /* Take arguments literally.  Don't glob */
+    queue_signals();
     while ((asg = getasg(*argv++))) {
 	if (asg->value && !ops['L']) {
 	    /* The argument is of the form foo=bar and we are not *
@@ -2694,6 +2770,7 @@ bin_alias(char *name, char **argv, char *ops, int func)
 	} else
 	    returnval = 1;
     }
+    unqueue_signals();
     return returnval;
 }
 
@@ -2774,7 +2851,10 @@ bin_print(char *name, char **args, char *ops, int func)
 	}
 	/* -D option -- interpret as a directory, and use ~ */
 	if(ops['D']) {
-	    Nameddir d = finddir(args[n]);
+	    Nameddir d;
+
+	    queue_signals();
+	    d = finddir(args[n]);
 	    if(d) {
 		char *arg = zhalloc(strlen(args[n]) + 1);
 		sprintf(arg, "~%s%s", d->nam,
@@ -2782,12 +2862,15 @@ bin_print(char *name, char **args, char *ops, int func)
 		args[n] = arg;
 		len[n] = strlen(args[n]);
 	    }
+	    unqueue_signals();
 	}
     }
 
     /* -z option -- push the arguments onto the editing buffer stack */
     if (ops['z']) {
+	queue_signals();
 	zpushnode(bufstack, sepjoin(args, NULL, 0));
+	unqueue_signals();
 	return 0;
     }
     /* -s option -- add the arguments to the history list */
@@ -2795,6 +2878,7 @@ bin_print(char *name, char **args, char *ops, int func)
 	int nwords = 0, nlen, iwords;
 	char **pargs = args;
 
+	queue_signals();
 	ent = prepnexthistent();
 	while (*pargs++)
 	    nwords++;
@@ -2813,6 +2897,7 @@ bin_print(char *name, char **args, char *ops, int func)
 	ent->stim = ent->ftim = time(NULL);
 	ent->flags = 0;
 	addhistnode(histtab, ent->text, ent);
+	unqueue_signals();
 	return 0;
     }
     /* -u and -p -- output to other than standard output */
@@ -2908,10 +2993,12 @@ bin_shift(char *name, char **argv, char *ops, int func)
     char **s;
  
     /* optional argument can be either numeric or an array */
+    queue_signals();
     if (*argv && !getaparam(*argv))
         num = mathevali(*argv++);
  
     if (num < 0) {
+	unqueue_signals();
         zwarnnam(name, "argument to shift must be non-negative", NULL, 0);
         return 1;
     }
@@ -2940,6 +3027,7 @@ bin_shift(char *name, char **argv, char *ops, int func)
 	    pparams = s;
 	}
     }
+    unqueue_signals();
     return ret;
 }
 
@@ -3169,7 +3257,7 @@ zexit(int val, int from_signal)
 	}
     }
     if (sigtrapped[SIGEXIT])
-	dotrap(SIGEXIT, 1);
+	dotrap(SIGEXIT);
     runhookdef(EXITHOOK, NULL);
     if (mypid != getpid())
 	_exit(val);
@@ -3415,7 +3503,7 @@ bin_read(char *name, char **args, char *ops, int func)
 		    *bptr = readchar;
 		    val = 1;
 		    readchar = -1;
-		} else if ((val = ztrapread(readfd, bptr, nchars)) <= 0)
+		} else if ((val = read(readfd, bptr, nchars)) <= 0)
 		    break;
 	    
 		/* decrement number of characters read from number required */
@@ -3429,7 +3517,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 && ztrapread(SHTTY, &d, 1) == 1 && d != '\n');
+		while (val > 0 && read(SHTTY, &d, 1) == 1 && d != '\n');
 	    else
 		settyinfo(&shttyinfo);
 	    if (haso) {
@@ -3686,7 +3774,7 @@ zread(int izle, int *readchar)
     }
     for (;;) {
 	/* read a character from readfd */
-	ret = ztrapread(readfd, &cc, 1);
+	ret = read(readfd, &cc, 1);
 	switch (ret) {
 	case 1:
 	    /* return the character read */
@@ -3839,6 +3927,7 @@ bin_trap(char *name, char **argv, char *ops, int func)
 
     /* If given no arguments, list all currently-set traps */
     if (!*argv) {
+	queue_signals();
 	for (sig = 0; sig < VSIGCOUNT; sig++) {
 	    if (sigtrapped[sig] & ZSIG_FUNC) {
 		char fname[20];
@@ -3860,6 +3949,7 @@ bin_trap(char *name, char **argv, char *ops, int func)
 		}
 	    }
 	}
+	unqueue_signals();
 	return 0;
     }
 
diff --git a/Src/exec.c b/Src/exec.c
index dc57291dc..ce083da86 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -759,8 +759,6 @@ execsimple(Estate state)
     } else
 	lv = (execfuncs[code - WC_CURSH])(state, 0);
 
-    RUNTRAPS();
-
     return lastval = lv;
 }
 
@@ -892,19 +890,19 @@ sublist_done:
 	noerrexit = oldnoerrexit;
 
 	if (sigtrapped[SIGDEBUG])
-	    dotrap(SIGDEBUG, 1);
+	    dotrap(SIGDEBUG);
 
 	/* 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, 1);
+		dotrap(SIGZERR);
 		donetrap = 1;
 	    }
 	    if (lastval && isset(ERREXIT)) {
 		if (sigtrapped[SIGEXIT])
-		    dotrap(SIGEXIT, 1);
+		    dotrap(SIGEXIT);
 		if (mypid != getpid())
 		    _exit(lastval);
 		else
@@ -951,9 +949,10 @@ execpline(Estate state, wordcode slcode, int how, int last1)
     child_block();
 
     /* get free entry in job table and initialize it */
-    if ((thisjob = newjob = initjob()) == -1)
+    if ((thisjob = newjob = initjob()) == -1) {
+	child_unblock();
 	return 1;
-
+    }
     if (how & Z_TIMED)
 	jobtab[thisjob].stat |= STAT_TIMED;
 
@@ -1186,10 +1185,9 @@ 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);
-	RUNTRAPS();
-    } else {
+    else {
 	int old_list_pipe = list_pipe;
 	Wordcode next = state->pc + (*state->pc);
 	wordcode code;
@@ -1224,14 +1222,12 @@ 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;
@@ -1611,7 +1607,7 @@ setunderscore(char *str)
     }
 }
 
-/* These describe the type of espansions that need to be done on the words
+/* These describe the type of expansions that need to be done on the words
  * used in the thing we are about to execute. They are set in execcmd() and
  * used in execsubst() which might be called from one of the functions
  * called from execcmd() (like execfor() and so on). */
@@ -2274,6 +2270,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
 		if (subsh_close >= 0)
 		    zclose(subsh_close);
 		subsh_close = -1;
+
 		execshfunc((Shfunc) hn, args);
 #ifdef PATH_DEV_FD
 		for (i = 10; i <= max_zsh_fd; i++)
diff --git a/Src/glob.c b/Src/glob.c
index 8f2f54952..90b291459 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -279,14 +279,17 @@ insert(char *s, int checked)
     char *news = s;
     int statted = 0;
 
+    queue_signals();
     inserts = NULL;
 
     if (gf_listtypes || gf_markdirs) {
 	/* Add the type marker to the end of the filename */
 	mode_t mode;
 	checked = statted = 1;
-	if (statfullpath(s, &buf, 1))
+	if (statfullpath(s, &buf, 1)) {
+	    unqueue_signals();
 	    return;
+	}
 	mode = buf.st_mode;
 	if (gf_follow) {
 	    if (!S_ISLNK(mode) || statfullpath(s, &buf2, 0))
@@ -307,9 +310,10 @@ insert(char *s, int checked)
 	/* Go through the qualifiers, rejecting the file if appropriate */
 	struct qual *qo, *qn;
 
-	if (!statted && statfullpath(s, &buf, 1))
+	if (!statted && statfullpath(s, &buf, 1)) {
+	    unqueue_signals();
 	    return;
-
+	}
 	news = dyncat(pathbuf, news);
 
 	statted = 1;
@@ -330,16 +334,20 @@ insert(char *s, int checked)
 	     * vice versa.                                   */
 	    if ((!((qn->func) (news, bp, qn->data, qn->sdata)) ^ qn->sense) & 1) {
 		/* Try next alternative, or return if there are no more */
-		if (!(qo = qo->or))
+		if (!(qo = qo->or)) {
+		    unqueue_signals();
 		    return;
+		}
 		qn = qo;
 		continue;
 	    }
 	    qn = qn->next;
 	}
     } else if (!checked) {
-	if (statfullpath(s, NULL, 1))
+	if (statfullpath(s, NULL, 1)) {
+	    unqueue_signals();
 	    return;
+	}
 	statted = 1;
 	news = dyncat(pathbuf, news);
     } else
@@ -389,6 +397,7 @@ insert(char *s, int checked)
 	if (!inserts)
 	    break;
     }
+    unqueue_signals();
 }
 
 /* Check to see if str is eligible for filename generation. */
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 9a1010ec6..884c98412 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -560,11 +560,14 @@ int
 bin_hashinfo(char *nam, char **args, char *ops, int func)
 {
     HashTable ht;
+
     printf("----------------------------------------------------\n");
+    queue_signals();
     for(ht = firstht; ht; ht = ht->next) {
 	ht->printinfo(ht);
 	printf("----------------------------------------------------\n");
     }
+    unqueue_signals();
     return 0;
 }
 
diff --git a/Src/hist.c b/Src/hist.c
index 9149d479b..b9480d786 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -382,6 +382,7 @@ histsubchar(int c)
 
 	/* get event number */
 
+	queue_signals();
 	if (c == '?') {
 	    for (;;) {
 		c = ingetc();
@@ -397,6 +398,7 @@ histsubchar(int c)
 	    evset = 0;
 	    if (ev == -1) {
 		herrflush();
+		unqueue_signals();
 		zerr("no such event: %s", buf, 0);
 		return -1;
 	    }
@@ -450,6 +452,7 @@ histsubchar(int c)
 		evset = 1;
 	    } else if ((ev = hcomsearch(buf)) == -1) {
 		herrflush();
+		unqueue_signals();
 		zerr("event not found: %s", buf, 0);
 		return -1;
 	    } else
@@ -458,9 +461,10 @@ histsubchar(int c)
 
 	/* get the event */
 
-	if (!(ehist = gethist(defev = ev)))
+	if (!(ehist = gethist(defev = ev))) {
+	    unqueue_signals();
 	    return -1;
-
+	}
 	/* extract the relevant arguments */
 
 	argc = getargc(ehist);
@@ -473,6 +477,7 @@ histsubchar(int c)
 		    argc = getargc(ehist);
 		} else {
 		    herrflush();
+		    unqueue_signals();
 		    zerr("Ambiguous history reference", NULL, 0);
 		    return -1;
 		}
@@ -486,8 +491,10 @@ histsubchar(int c)
 	} else {
 	    inungetc(c);
 	    larg = farg = getargspec(argc, marg, evset);
-	    if (larg == -2)
+	    if (larg == -2) {
+		unqueue_signals();
 		return -1;
+	    }
 	    if (farg != -1)
 		cflag = 0;
 	    c = ingetc();
@@ -497,8 +504,10 @@ histsubchar(int c)
 	    } else if (c == '-') {
 		cflag = 0;
 		larg = getargspec(argc, marg, evset);
-		if (larg == -2)
+		if (larg == -2) {
+		    unqueue_signals();
 		    return -1;
+		}
 		if (larg == -1)
 		    larg = argc - 1;
 	    } else
@@ -508,8 +517,11 @@ histsubchar(int c)
 	    farg = 0;
 	if (larg == -1)
 	    larg = argc;
-	if (!(sline = getargs(ehist, farg, larg)))
+	if (!(sline = getargs(ehist, farg, larg))) {
+	    unqueue_signals();
 	    return -1;
+	}
+	unqueue_signals();
     }
 
     /* do the modifiers */
@@ -1000,10 +1012,12 @@ mod_export int
 hend(Eprog prog)
 {
     int flag, save = 1;
-    char *hf = getsparam("HISTFILE");
+    char *hf;
 
     DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline,
 	  "BUG: chline is NULL in hend()");
+    queue_signals();
+    hf = getsparam("HISTFILE");
     if (histdone & HISTFLAG_SETTY)
 	settyinfo(&shttyinfo);
     if (!(histactive & HA_NOINC))
@@ -1013,6 +1027,7 @@ hend(Eprog prog)
 	zfree(chwords, chwordlen*sizeof(short));
 	chline = NULL;
 	histactive = 0;
+	unqueue_signals();
 	return 1;
     }
     if (hist_ignore_all_dups != isset(HISTIGNOREALLDUPS)
@@ -1107,6 +1122,7 @@ hend(Eprog prog)
     if (isset(SHAREHISTORY)? histfileIsLocked() : isset(INCAPPENDHISTORY))
 	savehistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
     unlockhistfile(hf); /* It's OK to call this even if we aren't locked */
+    unqueue_signals();
     return !(flag & HISTFLAG_NOEXEC || errflag);
 }
 
diff --git a/Src/init.c b/Src/init.c
index 290384c1a..b07ac80d5 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, 1);
+		dotrap(SIGEXIT);
 	    exit(lastval);
 	}
 	if (justonce)
@@ -1022,6 +1022,7 @@ sourcehome(char *s)
 {
     char *h;
 
+    queue_signals();
     if (emulation == EMULATE_SH || emulation == EMULATE_KSH ||
 	!(h = getsparam("ZDOTDIR")))
 	h = home;
@@ -1030,6 +1031,7 @@ sourcehome(char *s)
 	/* Let source() complain if path is too long */
 	VARARR(char, buf, strlen(h) + strlen(s) + 2);
 	sprintf(buf, "%s/%s", h, s);
+	unqueue_signals();
 	source(buf);
     }
 }
diff --git a/Src/input.c b/Src/input.c
index e82d25011..8f33e3631 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -141,9 +141,7 @@ shingetline(void)
     for (;;) {
 	do {
 	    errno = 0;
-	    ALLOWTRAPS {
-		c = fgetc(bshin);
-	    } DISALLOWTRAPS;
+	    c = fgetc(bshin);
 	} while (c < 0 && errno == EINTR);
 	if (c < 0 || c == '\n') {
 	    if (c == '\n')
diff --git a/Src/jobs.c b/Src/jobs.c
index 966263645..c491094b3 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, 0);
+	dotrap(SIGCHLD);
 
     /* 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, 0);
+		dotrap(sig);
 		/* 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.
@@ -497,6 +497,7 @@ printtime(struct timeval *real, struct timeinfo *ti, char *desc)
     percent      =  100.0 * (ti->ut + ti->st)
 	/ (clktck * real->tv_sec + clktck * real->tv_usec / 1000000.0);
 
+    queue_signals();
     if (!(s = getsparam("TIMEFMT")))
 	s = DEFAULT_TIMEFMT;
 
@@ -546,6 +547,7 @@ printtime(struct timeval *real, struct timeinfo *ti, char *desc)
 		break;
 	} else
 	    putc(*s, stderr);
+    unqueue_signals();
     putc('\n', stderr);
     fflush(stderr);
 }
@@ -580,10 +582,13 @@ should_report_time(Job j)
     if (j->stat & STAT_TIMED)
 	return 1;
 
+    queue_signals();
     if (!(v = getvalue(&vbuf, &s, 0)) ||
 	(reporttime = getintvalue(v)) < 0) {
+	unqueue_signals();
 	return 0;
     }
+    unqueue_signals();
     /* can this ever happen? */
     if (!j->procs)
 	return 0;
@@ -868,9 +873,10 @@ havefiles(void)
 void
 waitforpid(pid_t pid)
 {
-    int first = 1;
+    int first = 1, q = queue_signal_level();
 
     /* child_block() around this loop in case #ifndef WNOHANG */
+    dont_queue_signals();
     child_block();		/* unblocked in child_suspend() */
     while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
 	if (first)
@@ -878,12 +884,11 @@ waitforpid(pid_t pid)
 	else
 	    kill(pid, SIGCONT);
 
-	ALLOWTRAPS {
-	    child_suspend(SIGINT);
-	} DISALLOWTRAPS;
+	child_suspend(SIGINT);
 	child_block();
     }
     child_unblock();
+    restore_queue_signals(q);
 }
 
 /* wait for a job to finish */
@@ -892,8 +897,10 @@ waitforpid(pid_t pid)
 static void
 zwaitjob(int job, int sig)
 {
+    int q = queue_signal_level();
     Job jn = jobtab + job;
 
+    dont_queue_signals();
     child_block();		 /* unblocked during child_suspend() */
     if (jn->procs) {		 /* if any forks were done         */
 	jn->stat |= STAT_LOCKED;
@@ -902,9 +909,7 @@ zwaitjob(int job, int sig)
 	while (!errflag && jn->stat &&
 	       !(jn->stat & STAT_DONE) &&
 	       !(interact && (jn->stat & STAT_STOPPED))) {
-	    ALLOWTRAPS {
-		child_suspend(sig);
-	    } DISALLOWTRAPS;
+	    child_suspend(sig);
 	    /* 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
@@ -926,6 +931,7 @@ zwaitjob(int job, int sig)
 	numpipestats = 1;
     }
     child_unblock();
+    restore_queue_signals(q);
 }
 
 /* wait for running job to finish */
@@ -1222,11 +1228,13 @@ bin_fg(char *name, char **argv, char *ops, int func)
 	    zwarnnam(name, "-Z requires one argument", NULL, 0);
 	    return 1;
 	}
+	queue_signals();
 	unmetafy(*argv, &len);
 	if(len > hackspace)
 	    len = hackspace;
 	memcpy(hackzero, *argv, len);
 	memset(hackzero + len, 0, hackspace - len);
+	unqueue_signals();
 	return 0;
     }
 
@@ -1292,6 +1300,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
 	    pid_t pid = (long)atoi(*argv);
 	    Job j;
 	    Process p;
+
 	    if (findproc(pid, &j, &p))
 		waitforpid(pid);
 	    else
diff --git a/Src/math.c b/Src/math.c
index 282622f73..bad958243 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -495,10 +495,12 @@ getcvar(char *s)
     mnumber mn;
     mn.type = MN_INTEGER;
 
+    queue_signals();
     if (!(t = getsparam(s)))
 	mn.u.l = 0;
     else
         mn.u.l = STOUC(*t == Meta ? t[1] ^ 32 : *t);
+    unqueue_signals();
     return mn;
 }
 
diff --git a/Src/mem.c b/Src/mem.c
index b21ef210f..5c995c634 100644
--- a/Src/mem.c
+++ b/Src/mem.c
@@ -115,9 +115,13 @@ static Heap fheap;
 mod_export Heap
 new_heaps(void)
 {
-    Heap h = heaps;
+    Heap h;
+
+    queue_signals();
+    h = heaps;
 
     fheap = heaps = NULL;
+    unqueue_signals();
 
     return h;
 }
@@ -130,6 +134,7 @@ old_heaps(Heap old)
 {
     Heap h, n;
 
+    queue_signals();
     for (h = heaps; h; h = n) {
 	n = h->next;
 	DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
@@ -141,6 +146,7 @@ old_heaps(Heap old)
     }
     heaps = old;
     fheap = NULL;
+    unqueue_signals();
 }
 
 /* Temporarily switch to other heaps (or back again). */
@@ -149,10 +155,14 @@ old_heaps(Heap old)
 mod_export Heap
 switch_heaps(Heap new)
 {
-    Heap h = heaps;
+    Heap h;
+
+    queue_signals();
+    h = heaps;
 
     heaps = new;
     fheap = NULL;
+    unqueue_signals();
 
     return h;
 }
@@ -166,6 +176,8 @@ pushheap(void)
     Heap h;
     Heapstack hs;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_push++;
 #endif
@@ -177,6 +189,7 @@ pushheap(void)
 	h->sp = hs;
 	hs->used = h->used;
     }
+    unqueue_signals();
 }
 
 /* reset heaps to previous state */
@@ -187,6 +200,8 @@ freeheap(void)
 {
     Heap h, hn, hl = NULL;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_free++;
 #endif
@@ -214,6 +229,8 @@ freeheap(void)
 	hl->next = NULL;
     else
 	heaps = NULL;
+
+    unqueue_signals();
 }
 
 /* reset heap to previous state and destroy state information */
@@ -225,6 +242,8 @@ popheap(void)
     Heap h, hn, hl = NULL;
     Heapstack hs;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_pop++;
 #endif
@@ -255,6 +274,8 @@ popheap(void)
 	hl->next = NULL;
     else
 	heaps = NULL;
+
+    unqueue_signals();
 }
 
 /* allocate memory from the current memory pool */
@@ -268,6 +289,8 @@ zhalloc(size_t size)
 
     size = (size + H_ISIZE - 1) & ~(H_ISIZE - 1);
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_m[size < (1024 * H_ISIZE) ? (size / H_ISIZE) : 1024]++;
 #endif
@@ -276,8 +299,12 @@ zhalloc(size_t size)
 
     for (h = (fheap ? fheap : heaps); h; h = h->next) {
 	if (HEAP_ARENA_SIZE >= (n = size + h->used)) {
+	    void *ret;
+
 	    h->used = n;
-	    return arena(h) + n - size;
+	    ret = arena(h) + n - size;
+	    unqueue_signals();
+	    return ret;
 	}
     }
     {
@@ -289,7 +316,6 @@ zhalloc(size_t size)
             /* tricky, see above */
 #endif
 
-	queue_signals();
 	n = HEAP_ARENA_SIZE > size ? HEAPSIZE : size + sizeof(*h);
 	for (hp = NULL, h = heaps; h; hp = h, h = h->next);
 
@@ -361,6 +387,7 @@ hrealloc(char *p, size_t old, size_t new)
 
     /* find the heap with p */
 
+    queue_signals();
     for (h = heaps, ph = NULL; h; ph = h, h = h->next)
 	if (p >= arena(h) && p < arena(h) + HEAP_ARENA_SIZE)
 	    break;
@@ -376,9 +403,12 @@ hrealloc(char *p, size_t old, size_t new)
 #ifdef ZSH_MEM_DEBUG
 	    memset(p, 0xff, old);
 #endif
+	    unqueue_signals();
 	    return ptr;
-	} else
+	} else {
+	    unqueue_signals();
 	    return new ? p : NULL;
+	}
     }
 
     DPUTS(p + old != arena(h) + h->used, "BUG: hrealloc more than allocated");
@@ -395,6 +425,7 @@ hrealloc(char *p, size_t old, size_t new)
 #else
 	    zfree(h, HEAPSIZE);
 #endif
+	    unqueue_signals();
 	    return NULL;
 	}
 #ifndef USE_MMAP
@@ -407,6 +438,7 @@ hrealloc(char *p, size_t old, size_t new)
 		heaps = h = (Heap) realloc(h, n);
 	}
 	h->used = new;
+	unqueue_signals();
 	return arena(h);
 #endif
     }
@@ -415,6 +447,7 @@ hrealloc(char *p, size_t old, size_t new)
 #endif
     if (h->used + (new - old) <= HEAP_ARENA_SIZE) {
 	h->used += new - old;
+	unqueue_signals();
 	return p;
     } else {
 	char *t = zhalloc(new);
@@ -423,6 +456,7 @@ hrealloc(char *p, size_t old, size_t new)
 #ifdef ZSH_MEM_DEBUG
 	memset(p, 0xff, old);
 #endif
+	unqueue_signals();
 	return t;
     }
 }
@@ -450,10 +484,12 @@ zalloc(size_t size)
 
     if (!size)
 	size = 1;
+    queue_signals();
     if (!(ptr = (void *) malloc(size))) {
 	zerr("fatal error: out of memory", NULL, 0);
 	exit(1);
     }
+    unqueue_signals();
 
     return ptr;
 }
@@ -466,10 +502,12 @@ zcalloc(size_t size)
 
     if (!size)
 	size = 1;
+    queue_signals();
     if (!(ptr = (void *) malloc(size))) {
 	zerr("fatal error: out of memory", NULL, 0);
 	exit(1);
     }
+    unqueue_signals();
     memset(ptr, 0, size);
 
     return ptr;
@@ -485,6 +523,7 @@ zcalloc(size_t size)
 mod_export void *
 zrealloc(void *ptr, size_t size)
 {
+    queue_signals();
     if (ptr) {
 	if (size) {
 	    /* Do normal realloc */
@@ -492,18 +531,22 @@ zrealloc(void *ptr, size_t size)
 		zerr("fatal error: out of memory", NULL, 0);
 		exit(1);
 	    }
+	    unqueue_signals();
 	    return ptr;
 	}
 	else
 	    /* If ptr is not NULL, but size is zero, *
 	     * then object pointed to is freed.      */
 	    free(ptr);
+
+	ptr = NULL;
     } else {
 	/* If ptr is NULL, then behave like malloc */
-	return malloc(size);
+	ptr = malloc(size);
     }
+    unqueue_signals();
 
-    return NULL;
+    return ptr;
 }
 
 /**/
@@ -1200,6 +1243,7 @@ bin_mem(char *name, char **argv, char *ops, int func)
     char *b, *c, buf[40];
     long u = 0, f = 0, to, cu;
 
+    queue_signals();
     if (ops['v']) {
 	printf("The lower and the upper addresses of the heap. Diff gives\n");
 	printf("the difference between them, i.e. the size of the heap.\n\n");
@@ -1328,6 +1372,7 @@ bin_mem(char *name, char **argv, char *ops, int func)
     if (h_m[1024])
 	printf("big\t%d\n", h_m[1024]);
 
+    unqueue_signals();
     return 0;
 }
 
diff --git a/Src/module.c b/Src/module.c
index 13b747f05..cd68627ae 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -763,10 +763,13 @@ load_module(char const *name)
      * chain of aliases.  This makes sure the actual module loaded
      * is the right one.
      */
+    queue_signals();
     if (!(node = find_module(name, 1, &name))) {
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
+	}
 	m = zcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	if (handle) {
@@ -782,19 +785,25 @@ load_module(char const *name)
 	    if (!set)
 		finish_module(m);
 	    delete_module(node);
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S | MOD_INIT_B;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 1;
     } 
     m = (Module) getdata(node);
-    if (m->flags & MOD_SETUP)
+    if (m->flags & MOD_SETUP) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_UNLOAD)
 	m->flags &= ~MOD_UNLOAD;
-    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle)
+    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_BUSY) {
 	zerr("circular dependencies for module %s", name, 0);
 	return 0;
@@ -804,14 +813,17 @@ load_module(char const *name)
 	for (n = firstnode(m->deps); n; incnode(n))
 	    if (!load_module((char *) getdata(n))) {
 		m->flags &= ~MOD_BUSY;
+		unqueue_signals();
 		return 0;
 	    }
     m->flags &= ~MOD_BUSY;
     if (!m->u.handle) {
 	handle = NULL;
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
+	}
 	if (handle) {
 	    m->u.handle = handle;
 	    m->flags |= MOD_SETUP;
@@ -825,6 +837,7 @@ load_module(char const *name)
 	    else
 		m->u.linked = NULL;
 	    m->flags &= ~MOD_SETUP;
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S;
@@ -837,10 +850,12 @@ load_module(char const *name)
 	else
 	    m->u.handle = NULL;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 0;
     }
     m->flags |= MOD_INIT_B;
     m->flags &= ~MOD_SETUP;
+    unqueue_signals();
     return 1;
 }
 
@@ -858,19 +873,23 @@ require_module(char *nam, const char *module, int res, int test)
 {
     Module m = NULL;
     LinkNode node;
+    int ret = 1;
 
     /* Resolve aliases and actual loadable module as for load_module */
+    queue_signals();
     node = find_module(module, 1, &module);
     if (node && (m = ((Module) getdata(node)))->u.handle &&
 	!(m->flags & MOD_UNLOAD)) {
 	if (test) {
+	    unqueue_signals();
 	    zwarnnam(nam, "module %s already loaded.", module, 0);
 	    return 0;
 	}
     } else
-	return load_module(module);
+	ret = load_module(module);
+    unqueue_signals();
 
-    return 1;
+    return ret;
 }
 
 /**/
@@ -941,6 +960,8 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
 {
     int ops_bcpf = ops['b'] || ops['c'] || ops['p'] || ops['f'];
     int ops_au = ops['a'] || ops['u'];
+    int ret = 1;
+
     if (ops_bcpf && !ops_au) {
 	zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u",
 		 NULL, 0);
@@ -967,24 +988,26 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
 	zwarnnam(nam, "-e cannot be combined with other options", NULL, 0);
 	return 1;
     }
+    queue_signals();
     if (ops['e'])
-	return bin_zmodload_exist(nam, args, ops);
+	ret = bin_zmodload_exist(nam, args, ops);
     else if (ops['d'])
-	return bin_zmodload_dep(nam, args, ops);
+	ret = bin_zmodload_dep(nam, args, ops);
     else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'] || ops['f']))
-	return bin_zmodload_auto(nam, args, ops);
+	ret = bin_zmodload_auto(nam, args, ops);
     else if (ops['c'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_cond(nam, args, ops);
+	ret = bin_zmodload_cond(nam, args, ops);
     else if (ops['f'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_math(nam, args, ops);
+	ret = bin_zmodload_math(nam, args, ops);
     else if (ops['p'] && !(ops['b'] || ops['c']))
-	return bin_zmodload_param(nam, args, ops);
+	ret = bin_zmodload_param(nam, args, ops);
     else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p']))
-	return bin_zmodload_load(nam, args, ops);
+	ret = bin_zmodload_load(nam, args, ops);
     else
 	zwarnnam(nam, "use only one of -b, -c, or -p", NULL, 0);
+    unqueue_signals();
 
-    return 1;
+    return ret;
 }
 
 /**/
@@ -1993,12 +2016,14 @@ add_autoparam(char *nam, char *module)
 {
     Param pm;
 
+    queue_signals();
     if ((pm = (Param) gethashnode2(paramtab, nam)))
 	unsetparam_pm(pm, 0, 1);
 
     pm = setsparam(nam, ztrdup(module));
 
     pm->flags |= PM_AUTOLOAD;
+    unqueue_signals();
 }
 
 /* List of math functions. */
diff --git a/Src/params.c b/Src/params.c
index 1c41d2fc2..c4e6127ba 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1806,6 +1806,7 @@ setsparam(char *s, char *val)
 	errflag = 1;
 	return NULL;
     }
+    queue_signals();
     if ((ss = strchr(s, '['))) {
 	*ss = '\0';
 	if (!(v = getvalue(&vbuf, &s, 1)))
@@ -1823,10 +1824,12 @@ setsparam(char *s, char *val)
 	}
     }
     if (!v && !(v = getvalue(&vbuf, &t, 1))) {
+	unqueue_signals();
 	zsfree(val);
 	return NULL;
     }
     setstrvalue(v, val);
+    unqueue_signals();
     return v->pm;
 }
 
@@ -1845,12 +1848,14 @@ setaparam(char *s, char **val)
 	errflag = 1;
 	return NULL;
     }
+    queue_signals();
     if ((ss = strchr(s, '['))) {
 	*ss = '\0';
 	if (!(v = getvalue(&vbuf, &s, 1)))
 	    createparam(t, PM_ARRAY);
 	*ss = '[';
 	if (v && PM_TYPE(v->pm->flags) == PM_HASHED) {
+	    unqueue_signals();
 	    zerr("attempt to set slice of associative array", NULL, 0);
 	    freearray(val);
 	    errflag = 1;
@@ -1869,9 +1874,12 @@ setaparam(char *s, char **val)
 	}
     }
     if (!v)
-	if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING)))
+	if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
+	    unqueue_signals();
 	    return NULL;
+	}
     setarrvalue(v, val);
+    unqueue_signals();
     return v->pm;
 }
 
@@ -1894,20 +1902,23 @@ sethparam(char *s, char **val)
 	zerr("nested associative arrays not yet supported", NULL, 0);
 	errflag = 1;
 	return NULL;
-    } else {
-	if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING)))
-	    createparam(t, PM_HASHED);
-	else if (!(PM_TYPE(v->pm->flags) & PM_HASHED) &&
-		 !(v->pm->flags & PM_SPECIAL)) {
-	    unsetparam(t);
-	    createparam(t, PM_HASHED);
-	    v = NULL;
-	}
+    }
+    queue_signals();
+    if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING)))
+	createparam(t, PM_HASHED);
+    else if (!(PM_TYPE(v->pm->flags) & PM_HASHED) &&
+	     !(v->pm->flags & PM_SPECIAL)) {
+	unsetparam(t);
+	createparam(t, PM_HASHED);
+	v = NULL;
     }
     if (!v)
-	if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING)))
+	if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
+	    unqueue_signals();
 	    return NULL;
+	}
     setarrvalue(v, val);
+    unqueue_signals();
     return v->pm;
 }
 
@@ -1926,6 +1937,7 @@ setiparam(char *s, zlong val)
 	errflag = 1;
 	return NULL;
     }
+    queue_signals();
     if (!(v = getvalue(&vbuf, &s, 1))) {
 	if ((ss = strchr(s, '[')))
 	    *ss = '\0';
@@ -1937,12 +1949,14 @@ setiparam(char *s, zlong val)
 	    DPUTS(!v, "BUG: value not found for new parameter");
 	} else {
 	    pm->u.val = val;
+	    unqueue_signals();
 	    return pm;
 	}
     }
     mnval.type = MN_INTEGER;
     mnval.u.l = val;
     setnumvalue(v, mnval);
+    unqueue_signals();
     return v->pm;
 }
 
@@ -1965,6 +1979,7 @@ setnparam(char *s, mnumber val)
 	errflag = 1;
 	return NULL;
     }
+    queue_signals();
     if (!(v = getvalue(&vbuf, &s, 1))) {
 	if ((ss = strchr(s, '[')))
 	    *ss = '\0';
@@ -1981,10 +1996,12 @@ setnparam(char *s, mnumber val)
 		pm->u.val = val.u.l;
 	    } else
 		pm->u.dval = val.u.d;
+	    unqueue_signals();
 	    return pm;
 	}
     }
     setnumvalue(v, val);
+    unqueue_signals();
     return v->pm;
 }
 
@@ -1996,10 +2013,12 @@ unsetparam(char *s)
 {
     Param pm;
 
+    queue_signals();
     if ((pm = (Param) (paramtab == realparamtab ?
 		       gethashnode2(paramtab, s) :
 		       paramtab->getnode(paramtab, s))))
 	unsetparam_pm(pm, 0, 1);
+    unqueue_signals();
 }
 
 /* Unset a parameter */
@@ -2614,9 +2633,11 @@ setlang(char *x)
     struct localename *ln;
 
     setlocale(LC_ALL, x ? x : "");
+    queue_signals();
     for (ln = lc_names; ln->name; ln++)
 	if ((x = getsparam(ln->name)))
 	    setlocale(ln->category, x);
+    unqueue_signals();
 }
 
 /**/
@@ -2624,8 +2645,11 @@ void
 lc_allsetfn(Param pm, char *x)
 {
     strsetfn(pm, x);
-    if (!x)
+    if (!x) {
+	queue_signals();
 	setlang(getsparam("LANG"));
+	unqueue_signals();
+    }
     else
 	setlocale(LC_ALL, x);
 }
@@ -2647,12 +2671,14 @@ lcsetfn(Param pm, char *x)
     strsetfn(pm, x);
     if (getsparam("LC_ALL"))
 	return;
+    queue_signals();
     if (!x)
 	x = getsparam("LANG");
 
     for (ln = lc_names; ln->name; ln++)
 	if (!strcmp(ln->name, pm->nam))
 	    setlocale(ln->category, x ? x : "");
+    unqueue_signals();
 }
 #endif /* USE_LOCALE */
 
diff --git a/Src/parse.c b/Src/parse.c
index fafe65f43..4d9a48370 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2312,7 +2312,7 @@ dump_find_func(Wordcode h, char *name)
 int
 bin_zcompile(char *nam, char **args, char *ops, int func)
 {
-    int map, flags;
+    int map, flags, ret;
     char *dump;
 
     if ((ops['k'] && ops['z']) || (ops['R'] && ops['M']) ||
@@ -2359,15 +2359,22 @@ bin_zcompile(char *nam, char **args, char *ops, int func)
     }
     map = (ops['M'] ? 2 : (ops['R'] ? 0 : 1));
 
-    if (!args[1] && !(ops['c'] || ops['a']))
-	return build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map, flags);
-
+    if (!args[1] && !(ops['c'] || ops['a'])) {
+	queue_signals();
+	ret = build_dump(nam, dyncat(*args, FD_EXT), args, ops['U'], map, flags);
+	unqueue_signals();
+	return ret;
+    }
     dump = (strsfx(FD_EXT, *args) ? *args : dyncat(*args, FD_EXT));
 
-    return ((ops['c'] || ops['a']) ?
-	    build_cur_dump(nam, dump, args + 1, ops['m'], map,
-			   (ops['c'] ? 1 : 0) | (ops['a'] ? 2 : 0)) :
-	    build_dump(nam, dump, args + 1, ops['U'], map, flags));
+    queue_signals();
+    ret = ((ops['c'] || ops['a']) ?
+	   build_cur_dump(nam, dump, args + 1, ops['m'], map,
+			  (ops['c'] ? 1 : 0) | (ops['a'] ? 2 : 0)) :
+	   build_dump(nam, dump, args + 1, ops['U'], map, flags));
+    unqueue_signals();
+
+    return ret;
 }
 
 /* Load the header of a dump file. Returns NULL if the file isn't a
@@ -2825,9 +2832,12 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
     int rd, rc, rn;
     char *dig, *wc;
 
-    if (strsfx(FD_EXT, path))
-	return check_dump_file(path, NULL, name, ksh);
-
+    if (strsfx(FD_EXT, path)) {
+	queue_signals();
+	prog = check_dump_file(path, NULL, name, ksh);
+	unqueue_signals();
+	return prog;
+    }
     dig = dyncat(path, FD_EXT);
     wc = dyncat(file, FD_EXT);
 
@@ -2839,20 +2849,24 @@ try_dump_file(char *path, char *name, char *file, int *ksh)
      * both the uncompiled function file and its compiled version (or they
      * don't exist) and the digest file contains the definition for the
      * function. */
+    queue_signals();
     if (!rd &&
 	(rc || std.st_mtime > stc.st_mtime) &&
 	(rn || std.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(dig, &std, name, ksh)))
+	(prog = check_dump_file(dig, &std, name, ksh))) {
+	unqueue_signals();
 	return prog;
-
+    }
     /* No digest file. Now look for the per-function compiled file. */
     if (!rc &&
 	(rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, &stc, name, ksh)))
+	(prog = check_dump_file(wc, &stc, name, ksh))) {
+	unqueue_signals();
 	return prog;
-
+    }
     /* No compiled file for the function. The caller (getfpfunc() will
      * check if the directory contains the uncompiled file for it. */
+    unqueue_signals();
     return NULL;
 }
 
@@ -2872,18 +2886,24 @@ try_source_file(char *file)
     else
 	tail = file;
 
-    if (strsfx(FD_EXT, file))
-	return check_dump_file(file, NULL, tail, NULL);
-
+    if (strsfx(FD_EXT, file)) {
+	queue_signals();
+	prog = check_dump_file(file, NULL, tail, NULL);
+	unqueue_signals();
+	return prog;
+    }
     wc = dyncat(file, FD_EXT);
 
     rc = stat(wc, &stc);
     rn = stat(file, &stn);
 
+    queue_signals();
     if (!rc && (rn || stc.st_mtime > stn.st_mtime) &&
-	(prog = check_dump_file(wc, &stc, tail, NULL)))
+	(prog = check_dump_file(wc, &stc, tail, NULL))) {
+	unqueue_signals();
 	return prog;
-
+    }
+    unqueue_signals();
     return NULL;
 }
 
diff --git a/Src/prompt.c b/Src/prompt.c
index cca6da21f..b90bfff2a 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -372,12 +372,15 @@ putpromptchar(int doprint, int endchar)
 		bp += strlen(bp);
 		break;
 	    case 'M':
+		queue_signals();
 		if ((hostnam = getsparam("HOST")))
 		    stradd(hostnam);
+		unqueue_signals();
 		break;
 	    case 'm':
 		if (!arg)
 		    arg++;
+		queue_signals();
 		if (!(hostnam = getsparam("HOST")))
 		    break;
 		if (arg < 0) {
@@ -394,6 +397,7 @@ putpromptchar(int doprint, int endchar)
 		    stradd(hostnam);
 		    *ss = t0;
 		}
+		unqueue_signals();
 		break;
 	    case 'S':
 		txtchangeset(TXTSTANDOUT, TXTNOSTANDOUT);
diff --git a/Src/signals.c b/Src/signals.c
index 693337dbd..47599a414 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -497,7 +497,7 @@ handler(int sig)
  
     case SIGHUP:
         if (sigtrapped[SIGHUP])
-            dotrap(SIGHUP, 0);
+            dotrap(SIGHUP);
         else {
             stopmsg = 1;
             zexit(SIGHUP, 1);
@@ -506,7 +506,7 @@ handler(int sig)
  
     case SIGINT:
         if (sigtrapped[SIGINT])
-            dotrap(SIGINT, 0);
+            dotrap(SIGINT);
         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, 0);
+	    dotrap(SIGWINCH);
         break;
 #endif
 
     case SIGALRM:
         if (sigtrapped[SIGALRM]) {
 	    int tmout;
-            dotrap(SIGALRM, 0);
+            dotrap(SIGALRM);
 
 	    if ((tmout = getiparam("TMOUT")))
 		alarm(tmout);           /* reset the alarm */
@@ -549,7 +549,7 @@ handler(int sig)
         break;
  
     default:
-        dotrap(sig, 0);
+        dotrap(sig);
         break;
     }   /* end of switch(sig) */
  
@@ -703,6 +703,7 @@ settrap(int sig, Eprog l)
      * Call unsettrap() unconditionally, to make sure trap is saved
      * if necessary.
      */
+    queue_signals();
     unsettrap(sig);
 
     sigfuncs[sig] = l;
@@ -729,6 +730,7 @@ settrap(int sig, Eprog l)
      * works just the same.
      */
     sigtrapped[sig] |= (locallevel << ZSIG_SHIFT);
+    unqueue_signals();
     return 0;
 }
 
@@ -736,9 +738,13 @@ settrap(int sig, Eprog l)
 void
 unsettrap(int sig)
 {
-    HashNode hn = removetrap(sig);
+    HashNode hn;
+
+    queue_signals();
+    hn = removetrap(sig);
     if (hn)
 	shfunctab->freenode(hn);
+    unqueue_signals();
 }
 
 /**/
@@ -751,6 +757,7 @@ removetrap(int sig)
 	(jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN)))
 	return NULL;
 
+    queue_signals();
     trapped = sigtrapped[sig];
     /*
      * Note that we save the trap here even if there isn't an existing
@@ -762,9 +769,10 @@ removetrap(int sig)
 	(!trapped || locallevel > (sigtrapped[sig] >> ZSIG_SHIFT)))
 	dosavetrap(sig, locallevel);
 
-    if (!trapped)
+    if (!trapped) {
+	unqueue_signals();
         return NULL;
-
+    }
     sigtrapped[sig] = 0;
     if (sig == SIGINT && interact) {
 	/* PWS 1995/05/16:  added test for interactive, also noholdintr() *
@@ -790,6 +798,7 @@ removetrap(int sig)
      */
     if (trapped & ZSIG_FUNC) {
 	char func[20];
+	HashNode node;
 
 	sprintf(func, "TRAP%s", sigs[sig]);
 	/*
@@ -797,11 +806,15 @@ removetrap(int sig)
 	 * that calls back into unsettrap();
 	 */
 	sigfuncs[sig] = NULL;
-	return removehashnode(shfunctab, func);
+	node = removehashnode(shfunctab, func);
+	unqueue_signals();
+
+	return node;
     } else if (sigfuncs[sig]) {
 	freeeprog(sigfuncs[sig]);
 	sigfuncs[sig] = NULL;
     }
+    unqueue_signals();
 
     return NULL;
 }
@@ -966,56 +979,15 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
 	*sigtr &= ~ZSIG_IGNORED;
 }
 
-/* != 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. */
+/* Standard call to execute a trap for a given signal. */
 
 /**/
 void
-dotrap(int sig, int now)
+dotrap(int 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;
+    dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
 }
diff --git a/Src/signals.h b/Src/signals.h
index 45978dd1e..4ac19aa3e 100644
--- a/Src/signals.h
+++ b/Src/signals.h
@@ -73,26 +73,34 @@
  * queue signals, it is probably overkill for zsh to do  *
  * this, but it shouldn't hurt anything to do it anyway. */
 
-/* Right now I'm queueing all signals, but maybe we only *
- * need to queue SIGCHLD.  Anybody know?                 */
-
-#define MAX_QUEUE_SIZE 16
+#define MAX_QUEUE_SIZE 128
 
 #define queue_signals()    (queueing_enabled++)
 
+#define run_queued_signals() do { \
+    while (queue_front != queue_rear) {      /* while signals in queue */ \
+	sigset_t oset; \
+	queue_front = (queue_front + 1) % MAX_QUEUE_SIZE; \
+	oset = signal_setmask(signal_mask_queue[queue_front]); \
+	handler(signal_queue[queue_front]);  /* handle queued signal   */ \
+	signal_setmask(oset); \
+    } \
+} while (0)
+
 #define unqueue_signals()  do { \
     DPUTS(!queueing_enabled, "BUG: unqueue_signals called but not queueing"); \
-    if (!--queueing_enabled) { \
-	while (queue_front != queue_rear) {      /* while signals in queue */ \
-	    sigset_t oset; \
-	    queue_front = (queue_front + 1) % MAX_QUEUE_SIZE; \
-	    oset = signal_setmask(signal_mask_queue[queue_front]); \
-	    handler(signal_queue[queue_front]);  /* handle queued signal   */ \
-	    signal_setmask(oset); \
-	} \
-    } \
+    if (!--queueing_enabled) run_queued_signals(); \
 } while (0)
 
+#define queue_signal_level() queueing_enabled
+
+#define dont_queue_signals() do { \
+    queueing_enabled = 0; \
+    run_queued_signals(); \
+} while (0)
+
+#define restore_queue_signals(q) (queueing_enabled = (q))
+
 
 /* Make some signal functions faster. */
 
@@ -117,9 +125,3 @@ extern sigset_t signal_block _((sigset_t));
 #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/subst.c b/Src/subst.c
index 0cb985d71..bb90faf0c 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -51,6 +51,7 @@ prefork(LinkList list, int flags)
 {
     LinkNode node;
 
+    queue_signals();
     for (node = firstnode(list); node; incnode(node)) {
 	char *str, c;
 
@@ -61,14 +62,18 @@ prefork(LinkList list, int flags)
 		setdata(node, (void *) getproc(str));	/* <(...) or >(...) */
 	    else
 		setdata(node, (void *) getoutputfile(str));	/* =(...) */
-	    if (!getdata(node))
+	    if (!getdata(node)) {
+		unqueue_signals();
 		return;
+	    }
 	} else {
 	    if (isset(SHFILEEXPANSION))
 		filesub((char **)getaddrdata(node),
 			flags & (PF_TYPESET|PF_ASSIGN));
-	    if (!(node = stringsubst(list, node, flags & PF_SINGLE)))
+	    if (!(node = stringsubst(list, node, flags & PF_SINGLE))) {
+		unqueue_signals();
 		return;
+	    }
 	}
     }
     for (node = firstnode(list); node; incnode(node)) {
@@ -82,9 +87,12 @@ prefork(LinkList list, int flags)
 			flags & (PF_TYPESET|PF_ASSIGN));
 	} else if (!(flags & PF_SINGLE))
 	    uremnode(list, node);
-	if (errflag)
+	if (errflag) {
+	    unqueue_signals();
 	    return;
+	}
     }
+    unqueue_signals();
 }
 
 /**/
diff --git a/Src/utils.c b/Src/utils.c
index 11908435c..3bdaef307 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -691,12 +691,16 @@ preprompt(void)
 
 	if (mailpath && *mailpath && **mailpath)
 	    checkmailpath(mailpath);
-	else if ((mailfile = getsparam("MAIL")) && *mailfile) {
-	    char *x[2];
-
-	    x[0] = mailfile;
-	    x[1] = NULL;
-	    checkmailpath(x);
+	else {
+	    queue_signals();
+	    if ((mailfile = getsparam("MAIL")) && *mailfile) {
+		char *x[2];
+
+		x[0] = mailfile;
+		x[1] = NULL;
+		checkmailpath(x);
+	    }
+	    unqueue_signals();
 	}
 	lastmailcheck = time(NULL);
     }
@@ -1091,17 +1095,21 @@ zclose(int fd)
 mod_export char *
 gettempname(void)
 {
-    char *s;
+    char *s, *ret;
  
+    queue_signals();
     if (!(s = getsparam("TMPPREFIX")))
 	s = DEFAULT_TMPPREFIX;
  
 #ifdef HAVE__MKTEMP
     /* Zsh uses mktemp() safely, so silence the warnings */
-    return ((char *) _mktemp(dyncat(unmeta(s), "XXXXXX")));
+    ret = ((char *) _mktemp(dyncat(unmeta(s), "XXXXXX")));
 #else
-    return ((char *) mktemp(dyncat(unmeta(s), "XXXXXX")));
+    ret = ((char *) mktemp(dyncat(unmeta(s), "XXXXXX")));
 #endif
+    unqueue_signals();
+
+    return ret;
 }
 
 /* Check if a string contains a token */
@@ -1418,38 +1426,12 @@ 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 (ztrapread(SHTTY, &c, 1) != 1) {
+    while (read(SHTTY, &c, 1) != 1) {
 	if (errno != EINTR || errflag || retflag || breaks || contflag)
 	    return -1;
     }
@@ -1467,7 +1449,7 @@ noquery(int purge)
     ioctl(SHTTY, FIONREAD, (char *)&val);
     if (purge) {
 	for (; val; val--)
-	    ztrapread(SHTTY, &c, 1);
+	    read(SHTTY, &c, 1);
     }
 #endif
 
@@ -2122,12 +2104,14 @@ mod_export void
 zbeep(void)
 {
     char *vb;
+    queue_signals();
     if ((vb = getsparam("ZBEEP"))) {
 	int len;
 	vb = getkeystring(vb, &len, 2, NULL);
 	write(SHTTY, vb, len);
     } else if (isset(BEEP))
 	write(SHTTY, "\07", 1);
+    unqueue_signals();
 }
 
 /**/
diff --git a/Src/watch.c b/Src/watch.c
index 2532e0a63..4f63a5bd9 100644
--- a/Src/watch.c
+++ b/Src/watch.c
@@ -235,7 +235,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
 # endif /* WATCH_UTMP_UT_HOST */
 
     while (*fmt)
-	if (*fmt == '\\')
+	if (*fmt == '\\') {
 	    if (*++fmt) {
 		if (prnt)
 		    putchar(*fmt);
@@ -244,6 +244,7 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
 		return fmt;
 	    else
 		break;
+	}
 	else if (*fmt == fini)
 	    return ++fmt;
 	else if (*fmt != '%') {
@@ -490,8 +491,6 @@ dowatch(void)
     int uct, wct;
 
     s = watch;
-    if (!(fmt = getsparam("WATCHFMT")))
-	fmt = DEFAULT_WATCHFMT;
 
     holdintr();
     if (!wtab) {
@@ -541,6 +540,9 @@ dowatch(void)
 	free(utab);
 	return;
     }
+    queue_signals();
+    if (!(fmt = getsparam("WATCHFMT")))
+	fmt = DEFAULT_WATCHFMT;
     while ((uct || wct) && !errflag)
 	if (!uct || (wct && ucmp(uptr, wptr) > 0))
 	    wct--, watchlog(0, wptr++, s, fmt);
@@ -548,6 +550,7 @@ dowatch(void)
 	    uct--, watchlog(1, uptr++, s, fmt);
 	else
 	    uptr++, wptr++, wct--, uct--;
+    unqueue_signals();
     free(wtab);
     wtab = utab;
     wtabsz = utabsz;