summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2004-04-21 11:18:45 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2004-04-21 11:18:45 +0000
commit5747147afff8a991561a490eca38892c1971a901 (patch)
treedad6c366403973811fe775a49922f3fa724a4eb4
parentf34d9be61b047beadb24748163c1bc59a7eff9d3 (diff)
downloadzsh-5747147afff8a991561a490eca38892c1971a901.tar.gz
zsh-5747147afff8a991561a490eca38892c1971a901.zip
19809: improve NO_TRAPS_ASYNC by queueing traps alone
-rw-r--r--ChangeLog7
-rw-r--r--Src/jobs.c11
-rw-r--r--Src/signals.c23
-rw-r--r--Src/signals.h17
4 files changed, 48 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 7246c1268..a0a4f29ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-04-21 Peter Stephenson <pws@csr.com>
+
+ * 19809: Src/jobs.c, Src/signals.c, Src/signals.h: improve
+ zsh-users/7365 by only queuing traps when TRAPS_ASYNC is set.
+ This avoids any nasty races, including one reported by Vincent
+ Stemen.
+
2004-04-21 Oliver Kiddle <opk@zsh.org>
* 19806: Src/prompt.c: fix bug with %v expansion and negative index
diff --git a/Src/jobs.c b/Src/jobs.c
index 072a91744..7d89a7dbb 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -994,11 +994,8 @@ zwaitjob(int job, int sig)
int q = queue_signal_level();
Job jn = jobtab + job;
- queue_not_sigchld++;
- if (isset(TRAPSASYNC))
- dont_queue_signals();
- else
- queue_signals();
+ dont_queue_signals();
+ queue_traps();
child_block(); /* unblocked during child_suspend() */
if (jn->procs || jn->auxprocs) { /* if any forks were done */
jn->stat |= STAT_LOCKED;
@@ -1029,10 +1026,8 @@ zwaitjob(int job, int sig)
numpipestats = 1;
}
child_unblock();
+ dont_queue_traps();
restore_queue_signals(q);
- if (!queueing_enabled)
- run_queued_signals();
- queue_not_sigchld--;
}
/* wait for running job to finish */
diff --git a/Src/signals.c b/Src/signals.c
index 8939d1ba1..25febc85d 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -49,12 +49,19 @@ mod_export int nsigtrapped;
/* Variables used by signal queueing */
/**/
-mod_export int queueing_enabled, queue_front, queue_rear, queue_not_sigchld;
+mod_export int queueing_enabled, queue_front, queue_rear;
/**/
mod_export int signal_queue[MAX_QUEUE_SIZE];
/**/
mod_export sigset_t signal_mask_queue[MAX_QUEUE_SIZE];
+/* Variables used by trap queueing */
+
+/**/
+mod_export int trap_queueing_enabled, trap_queue_front, trap_queue_rear;
+/**/
+mod_export int trap_queue[MAX_QUEUE_SIZE];
+
/* This is only used on machines that don't understand signal sets. *
* On SYSV machines this will represent the signals that are blocked *
* (held) using sighold. On machines which can't block signals at *
@@ -426,7 +433,7 @@ zhandler(int sig)
#endif
/* Are we queueing signals now? */
- if (queueing_enabled && (sig != SIGCHLD || !queue_not_sigchld)) {
+ if (queueing_enabled) {
int temp_rear = ++queue_rear % MAX_QUEUE_SIZE;
DPUTS(temp_rear == queue_front, "BUG: signal queue full");
@@ -1058,5 +1065,17 @@ dotrap(int sig)
if ((sigtrapped[sig] & ZSIG_IGNORED) || !sigfuncs[sig] || errflag)
return;
+ /* Adapted from signal queueing in zhandler */
+ if (trap_queueing_enabled && !isset(TRAPSASYNC)) {
+ int temp_rear = ++trap_queue_rear % MAX_QUEUE_SIZE;
+
+ DPUTS(temp_rear == trap_queue_front, "BUG: trap queue full");
+ if (temp_rear != trap_queue_front) {
+ trap_queue_rear = temp_rear;
+ trap_queue[trap_queue_rear] = sig;
+ }
+ return;
+ }
+
dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
}
diff --git a/Src/signals.h b/Src/signals.h
index 4b8197d84..e86906ebc 100644
--- a/Src/signals.h
+++ b/Src/signals.h
@@ -101,6 +101,23 @@
#define restore_queue_signals(q) (queueing_enabled = (q))
+/*
+ * Similar (but simpler) mechanism used for queueing traps.
+ * Only needed if NO_TRAPS_ASYNC is set.
+ */
+#define queue_traps() (trap_queueing_enabled++)
+
+#define run_queued_traps() do { \
+ while (trap_queue_front != trap_queue_rear) { /* while traps in queue */ \
+ trap_queue_front = (trap_queue_front + 1) % MAX_QUEUE_SIZE; \
+ dotrap(trap_queue[trap_queue_front]); /* handle queued trap */ \
+ } \
+} while (0)
+
+#define dont_queue_traps() do { \
+ trap_queueing_enabled = 0; \
+ run_queued_traps(); \
+} while (0)
/* Make some signal functions faster. */