diff options
Diffstat (limited to 'usr/src/uts/common/os/sig.c')
-rw-r--r-- | usr/src/uts/common/os/sig.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c index 4a2efd89cb..3425046072 100644 --- a/usr/src/uts/common/os/sig.c +++ b/usr/src/uts/common/os/sig.c @@ -436,10 +436,10 @@ issig_justlooking(void) if ((lwp->lwp_asleep && MUSTRETURN(p, t)) || (p->p_flag & (SEXITLWPS|SKILLED)) || - (lwp->lwp_nostop == 0 && - (p->p_stopsig | (p->p_flag & (SHOLDFORK1|SHOLDWATCH)) | - (t->t_proc_flag & - (TP_PRSTOP|TP_HOLDLWP|TP_CHKPT|TP_PAUSE)))) || + (!lwp->lwp_nostop_r && ((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) | + (t->t_proc_flag & TP_HOLDLWP))) || + (!lwp->lwp_nostop && (p->p_stopsig | (t->t_proc_flag & + (TP_PRSTOP|TP_CHKPT|TP_PAUSE)))) || lwp->lwp_cursig) return (1); @@ -577,9 +577,15 @@ issig_forreal(void) * or is executing lwp_suspend() on this lwp. * Again, go back to top of loop to check if an exit * or hold event has occurred while stopped. + * We explicitly allow this form of stopping of one + * lwp in a process by another lwp in the same process, + * even if lwp->lwp_nostop is set, because otherwise a + * process can become deadlocked on a fork1(). + * Allow this only if lwp_nostop_r is not set, + * to avoid a recursive call to prstop(). */ if (((p->p_flag & (SHOLDFORK1|SHOLDWATCH)) || - (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop) { + (t->t_proc_flag & TP_HOLDLWP)) && !lwp->lwp_nostop_r) { stop(PR_SUSPENDED, SUSPEND_NORMAL); continue; } @@ -845,9 +851,11 @@ stop(int why, int what) /* * Make sure we don't deadlock on a recursive call to prstop(). - * prstop() sets the lwp_nostop flag. + * prstop() sets the lwp_nostop_r flag and increments lwp_nostop. */ - if (lwp->lwp_nostop) + if (lwp->lwp_nostop_r || + (lwp->lwp_nostop && + (why != PR_SUSPENDED || what != SUSPEND_NORMAL))) return; /* |