summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread/thr_sig.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread/thr_sig.c')
-rw-r--r--lib/libpthread/thread/thr_sig.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c
index 6e95cdd..cef8399 100644
--- a/lib/libpthread/thread/thr_sig.c
+++ b/lib/libpthread/thread/thr_sig.c
@@ -217,7 +217,10 @@ _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
THR_IS_EXITING(thread) || THR_IS_SUSPENDED(thread)) {
KSE_SCHED_UNLOCK(curkse, thread->kseg);
_thr_ref_delete(NULL, thread);
- } else if (SIGISMEMBER(thread->sigmask, sig)) {
+ } else if ((thread->state == PS_SIGWAIT &&
+ SIGISMEMBER(thread->oldsigmask, sig)) ||
+ (thread->state != PS_SIGWAIT &&
+ SIGISMEMBER(thread->sigmask, sig))) {
KSE_SCHED_UNLOCK(curkse, thread->kseg);
_thr_ref_delete(NULL, thread);
} else {
@@ -415,10 +418,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
if ((pthread->state == PS_DEAD) ||
(pthread->state == PS_DEADLOCK) ||
THR_IS_EXITING(pthread) ||
- THR_IS_SUSPENDED(pthread) ||
- SIGISMEMBER(pthread->sigmask, sig)) {
+ THR_IS_SUSPENDED(pthread)) {
; /* Skip this thread. */
- } else if (pthread->state == PS_SIGWAIT) {
+ } else if (pthread->state == PS_SIGWAIT &&
+ !SIGISMEMBER(pthread->sigmask, sig)) {
/*
* retrieve signal from kernel, if it is job control
* signal, and sigaction is SIG_DFL, then we will
@@ -447,7 +450,9 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
*/
KSE_LOCK_RELEASE(curkse, &_thread_list_lock);
return (NULL);
- } else {
+ } else if (!SIGISMEMBER(pthread->sigmask, sig) ||
+ (!SIGISMEMBER(pthread->oldsigmask, sig) &&
+ pthread->state == PS_SIGWAIT)) {
if (pthread->state == PS_SIGSUSPEND) {
if (suspended_thread == NULL) {
suspended_thread = pthread;
@@ -490,6 +495,8 @@ void
_thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
struct pthread_sigframe *psf)
{
+ int interrupted = curthread->interrupted;
+ int timeout = curthread->timeout;
siginfo_t siginfo;
int i;
kse_critical_t crit;
@@ -563,6 +570,9 @@ _thr_sig_rundown(struct pthread *curthread, ucontext_t *ucp,
KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
_kse_critical_leave(&curthread->tmbx);
+ curthread->interrupted = interrupted;
+ curthread->timeout = timeout;
+
DBG_MSG("<<< thr_sig_rundown %p\n", curthread);
}
@@ -659,7 +669,8 @@ _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
#endif
if (pthread->curframe == NULL ||
- SIGISMEMBER(pthread->sigmask, sig) ||
+ (pthread->state != PS_SIGWAIT &&
+ SIGISMEMBER(pthread->sigmask, sig)) ||
THR_IN_CRITICAL(pthread)) {
/* thread is running or signal was being masked */
if (!fromproc) {
@@ -760,6 +771,9 @@ _thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
/* Increment the pending signal count. */
SIGADDSET(pthread->sigpend, sig);
pthread->check_pending = 1;
+ pthread->interrupted = 1;
+ pthread->sigmask = pthread->oldsigmask;
+ _thr_setrunnable_unlocked(pthread);
}
return;
@@ -823,6 +837,9 @@ thr_sig_check_state(struct pthread *pthread, int sig)
/* Increment the pending signal count. */
SIGADDSET(pthread->sigpend, sig);
pthread->check_pending = 1;
+ pthread->interrupted = 1;
+ pthread->sigmask = pthread->oldsigmask;
+ _thr_setrunnable_unlocked(pthread);
}
break;
OpenPOWER on IntegriCloud