diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Src/jobs.c | 11 | ||||
-rw-r--r-- | Src/signals.c | 23 | ||||
-rw-r--r-- | Src/signals.h | 17 |
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. */ |