ed7c627f46
Resolves: rhbz#1181685 Version: 6.18.01-13
92 lines
2.4 KiB
Diff
92 lines
2.4 KiB
Diff
From 788faac41b56f8b08e60f3456ad56c5a36fffa4c Mon Sep 17 00:00:00 2001
|
|
From: Pavel Raiskup <praiskup@redhat.com>
|
|
Date: Tue, 27 Jan 2015 07:05:26 +0100
|
|
Subject: [PATCH 16/16] tcsh: fix 'wait' hang
|
|
|
|
Make sure that SIGCHLD is blocked before we call
|
|
handle_pending_signals() for the first time and before we actually
|
|
check for pp->p_flags & PRUNNING to make sure that the SIGCHLD is
|
|
not leaked meanwhile.
|
|
|
|
Resolves: rhbz#1181685
|
|
|
|
---
|
|
Fixes | 4 ++++
|
|
sh.proc.c | 26 +++++++++++++++++++++++++-
|
|
2 files changed, 29 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/Fixes b/Fixes
|
|
index 8eac9d4..56915a9 100644
|
|
--- a/Fixes
|
|
+++ b/Fixes
|
|
@@ -1,3 +1,7 @@
|
|
+ 29. Pavel Raiskup fix hang with:
|
|
+ while (1)
|
|
+ ( date & ; wait )
|
|
+ end
|
|
6. V6.18.01 - 20120214
|
|
5. fix interruptible wait again
|
|
4. ignore bogus compiler overflow message
|
|
diff --git a/sh.proc.c b/sh.proc.c
|
|
index e32ebda..0c5fc25 100644
|
|
--- a/sh.proc.c
|
|
+++ b/sh.proc.c
|
|
@@ -593,22 +593,44 @@ void
|
|
dowait(Char **v, struct command *c)
|
|
{
|
|
struct process *pp;
|
|
+
|
|
+ /* the current block mask to be able to restore */
|
|
+ sigset_t old_mask;
|
|
+
|
|
+ /* block mask for critical section: OLD_MASK U {SIGCHLD} */
|
|
+ sigset_t block_mask;
|
|
+
|
|
+ /* ignore those during blocking sigsuspend:
|
|
+ OLD_MASK / {SIGCHLD, possibly(SIGINT)} */
|
|
sigset_t pause_mask;
|
|
+
|
|
int opintr_disabled, gotsig;
|
|
|
|
USE(c);
|
|
USE(v);
|
|
pjobs++;
|
|
+
|
|
sigprocmask(SIG_BLOCK, NULL, &pause_mask);
|
|
sigdelset(&pause_mask, SIGCHLD);
|
|
if (setintr)
|
|
sigdelset(&pause_mask, SIGINT);
|
|
+
|
|
+ /* critical section, block also SIGCHLD */
|
|
+ sigprocmask(SIG_BLOCK, NULL, &block_mask);
|
|
+ sigaddset(&block_mask, SIGCHLD);
|
|
+ sigprocmask(SIG_BLOCK, &block_mask, &old_mask);
|
|
+
|
|
+ /* detect older SIGCHLDs and remove PRUNNING flag from proclist */
|
|
+ (void)handle_pending_signals();
|
|
+
|
|
loop:
|
|
for (pp = proclist.p_next; pp; pp = pp->p_next)
|
|
if (pp->p_procid && /* pp->p_procid == pp->p_jobid && */
|
|
pp->p_flags & PRUNNING) {
|
|
- (void)handle_pending_signals();
|
|
+ /* wait for (or pick up alredy blocked) SIGCHLD */
|
|
sigsuspend(&pause_mask);
|
|
+
|
|
+ /* make the 'wait' interuptable by CTRL-C */
|
|
opintr_disabled = pintr_disabled;
|
|
pintr_disabled = 0;
|
|
gotsig = handle_pending_signals();
|
|
@@ -618,6 +640,8 @@ loop:
|
|
goto loop;
|
|
}
|
|
pjobs = 0;
|
|
+
|
|
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
|
}
|
|
|
|
/*
|
|
--
|
|
2.1.0
|
|
|