summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/port/threads/sigaction.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libc/port/threads/sigaction.c')
-rw-r--r--usr/src/lib/libc/port/threads/sigaction.c43
1 files changed, 14 insertions, 29 deletions
diff --git a/usr/src/lib/libc/port/threads/sigaction.c b/usr/src/lib/libc/port/threads/sigaction.c
index 8e52b04a8c..eecb8ebfa0 100644
--- a/usr/src/lib/libc/port/threads/sigaction.c
+++ b/usr/src/lib/libc/port/threads/sigaction.c
@@ -109,7 +109,8 @@ call_user_handler(int sig, siginfo_t *sip, ucontext_t *ucp)
rwlock_t *rwlp = &udp->siguaction[sig].sig_lock;
lrw_rdlock(rwlp);
(void) _private_memcpy(&uact, (void *)sap, sizeof (uact));
- if (sig == SIGCANCEL && (sap->sa_flags & SA_RESETHAND))
+ if ((sig == SIGCANCEL || sig == SIGAIOCANCEL) &&
+ (sap->sa_flags & SA_RESETHAND))
sap->sa_sigaction = SIG_DFL;
lrw_unlock(rwlp);
}
@@ -388,7 +389,8 @@ _libc_sigaction(int sig, const struct sigaction *nact, struct sigaction *oact)
tact.sa_flags = SA_SIGINFO;
else {
tact.sa_flags |= SA_SIGINFO;
- tact.sa_flags &= ~(SA_NODEFER | SA_RESETHAND);
+ tact.sa_flags &=
+ ~(SA_NODEFER | SA_RESETHAND | SA_RESTART);
}
tact.sa_sigaction = udp->sigacthandler;
tact.sa_mask = maskset;
@@ -437,28 +439,6 @@ setsigacthandler(void (*nsigacthandler)(int, siginfo_t *, void *),
}
/*
- * Calling set_parking_flag(curthread, 1) informs the kernel that we are
- * calling __lwp_park or ___lwp_cond_wait(). If we take a signal in
- * the unprotected (from signals) interval before reaching the kernel,
- * sigacthandler() will call set_parking_flag(curthread, 0) to inform
- * the kernel to return immediately from these system calls, giving us
- * a spurious wakeup but not a deadlock.
- */
-void
-set_parking_flag(ulwp_t *self, int park)
-{
- volatile sc_shared_t *scp;
-
- enter_critical(self);
- if ((scp = self->ul_schedctl) != NULL ||
- (scp = setup_schedctl()) != NULL)
- scp->sc_park = park;
- else if (park == 0) /* schedctl failed, do it the long way */
- __lwp_unpark(self->ul_lwpid);
- exit_critical(self);
-}
-
-/*
* Tell the kernel to block all signals.
* Use the schedctl interface, or failing that, use __lwp_sigmask().
* This action can be rescinded only by making a system call that
@@ -688,12 +668,15 @@ signal_init()
/*
* Common code for cancelling self in _sigcancel() and pthread_cancel().
- * If the thread is at a cancellation point (ul_cancelable) then just
- * return and let _canceloff() do the exit, else exit immediately if
- * async mode is in effect.
+ * First record the fact that a cancellation is pending.
+ * Then, if cancellation is disabled or if we are holding unprotected
+ * libc locks, just return to defer the cancellation.
+ * Then, if we are at a cancellation point (ul_cancelable) just
+ * return and let _canceloff() do the exit.
+ * Else exit immediately if async mode is in effect.
*/
void
-do_sigcancel()
+do_sigcancel(void)
{
ulwp_t *self = curthread;
@@ -702,8 +685,10 @@ do_sigcancel()
self->ul_cancel_pending = 1;
if (self->ul_cancel_async &&
!self->ul_cancel_disabled &&
+ self->ul_libc_locks == 0 &&
!self->ul_cancelable)
_pthread_exit(PTHREAD_CANCELED);
+ set_cancel_pending_flag(self, 0);
}
/*
@@ -728,7 +713,7 @@ setup_cancelsig(int sig)
act.sa_flags = SA_SIGINFO;
else {
act.sa_flags |= SA_SIGINFO;
- act.sa_flags &= ~(SA_NODEFER | SA_RESETHAND);
+ act.sa_flags &= ~(SA_NODEFER | SA_RESETHAND | SA_RESTART);
}
act.sa_sigaction = udp->sigacthandler;
act.sa_mask = maskset;