diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-07-07 04:28:23 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-07-07 04:28:23 +0000 |
commit | 8aa4e2d6856d1eed699b30ccca6163f8e501e183 (patch) | |
tree | 6539674ba4c0ff3018faf64006ac81eb9090ec5f /lib | |
parent | e95dd66c1f7fd662d47b34b5d83f1dcaa8b150e3 (diff) | |
download | FreeBSD-src-8aa4e2d6856d1eed699b30ccca6163f8e501e183.zip FreeBSD-src-8aa4e2d6856d1eed699b30ccca6163f8e501e183.tar.gz |
Avoid accessing user provided parameters in critical region.
Reviewed by: deischen
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libkse/thread/thr_attr_get_np.c | 5 | ||||
-rw-r--r-- | lib/libkse/thread/thr_cancel.c | 14 | ||||
-rw-r--r-- | lib/libkse/thread/thr_getschedparam.c | 8 | ||||
-rw-r--r-- | lib/libkse/thread/thr_join.c | 8 | ||||
-rw-r--r-- | lib/libkse/thread/thr_mutex_prioceiling.c | 8 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sigaction.c | 35 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sigmask.c | 16 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sigpending.c | 6 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sigsuspend.c | 11 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_attr_get_np.c | 5 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_cancel.c | 14 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_getschedparam.c | 8 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_join.c | 8 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_mutex_prioceiling.c | 8 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sigaction.c | 35 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sigmask.c | 16 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sigpending.c | 6 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sigsuspend.c | 11 |
18 files changed, 130 insertions, 92 deletions
diff --git a/lib/libkse/thread/thr_attr_get_np.c b/lib/libkse/thread/thr_attr_get_np.c index 4431824..e844acb 100644 --- a/lib/libkse/thread/thr_attr_get_np.c +++ b/lib/libkse/thread/thr_attr_get_np.c @@ -37,6 +37,7 @@ int _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) { struct pthread *curthread; + struct pthread_attr attr; int ret; if (pid == NULL || dst == NULL || *dst == NULL) @@ -45,9 +46,9 @@ _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) curthread = _get_curthread(); if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) return (ret); - - memcpy(*dst, &pid->attr, sizeof(struct pthread_attr)); + attr = pid->attr; _thr_ref_delete(curthread, pid); + memcpy(*dst, &attr, sizeof(struct pthread_attr)); return (0); } diff --git a/lib/libkse/thread/thr_cancel.c b/lib/libkse/thread/thr_cancel.c index 085f349..905891c 100644 --- a/lib/libkse/thread/thr_cancel.c +++ b/lib/libkse/thread/thr_cancel.c @@ -146,16 +146,12 @@ _pthread_setcancelstate(int state, int *oldstate) switch (state) { case PTHREAD_CANCEL_ENABLE: - if (oldstate != NULL) - *oldstate = ostate; curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE; if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0) need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DISABLE: - if (oldstate != NULL) - *oldstate = ostate; curthread->cancelflags |= PTHREAD_CANCEL_DISABLE; ret = 0; break; @@ -169,6 +165,9 @@ _pthread_setcancelstate(int state, int *oldstate) pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } + if (ret == 0 && oldstate != NULL) + *oldstate = ostate; + return (ret); } @@ -186,15 +185,11 @@ _pthread_setcanceltype(int type, int *oldtype) otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS; switch (type) { case PTHREAD_CANCEL_ASYNCHRONOUS: - if (oldtype != NULL) - *oldtype = otype; curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS; need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DEFERRED: - if (oldtype != NULL) - *oldtype = otype; curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS; ret = 0; break; @@ -208,6 +203,9 @@ _pthread_setcanceltype(int type, int *oldtype) pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } + if (ret == 0 && oldtype != NULL) + *oldtype = otype; + return (ret); } diff --git a/lib/libkse/thread/thr_getschedparam.c b/lib/libkse/thread/thr_getschedparam.c index d00e498..ad8486c 100644 --- a/lib/libkse/thread/thr_getschedparam.c +++ b/lib/libkse/thread/thr_getschedparam.c @@ -42,7 +42,7 @@ _pthread_getschedparam(pthread_t pthread, int *policy, struct sched_param *param) { struct pthread *curthread = _get_curthread(); - int ret; + int ret, tmp; if ((param == NULL) || (policy == NULL)) /* Return an invalid argument error: */ @@ -55,8 +55,9 @@ _pthread_getschedparam(pthread_t pthread, int *policy, THR_SCHED_LOCK(curthread, curthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); - *policy = pthread->attr.sched_policy; + tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, curthread); + *policy = tmp; ret = 0; } /* Find the thread in the list of active threads. */ @@ -65,9 +66,10 @@ _pthread_getschedparam(pthread_t pthread, int *policy, THR_SCHED_LOCK(curthread, pthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); - *policy = pthread->attr.sched_policy; + tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); + *policy = tmp; } return (ret); } diff --git a/lib/libkse/thread/thr_join.c b/lib/libkse/thread/thr_join.c index d6add88..592aa3a 100644 --- a/lib/libkse/thread/thr_join.c +++ b/lib/libkse/thread/thr_join.c @@ -41,6 +41,7 @@ int _pthread_join(pthread_t pthread, void **thread_return) { struct pthread *curthread = _get_curthread(); + void *tmp; kse_critical_t crit; int ret = 0; @@ -80,9 +81,8 @@ _pthread_join(pthread_t pthread, void **thread_return) } else { /* Lock the target thread while checking its state. */ if (pthread->state == PS_DEAD) { - if (thread_return != NULL) - /* Return the thread's return value: */ - *thread_return = pthread->ret; + /* Return the thread's return value: */ + tmp = pthread->ret; /* Detach the thread. */ pthread->attr.flags |= PTHREAD_DETACHED; @@ -103,6 +103,8 @@ _pthread_join(pthread_t pthread, void **thread_return) /* Remove the reference. */ _thr_ref_delete(curthread, pthread); + if (thread_return != NULL) + *thread_return = tmp; } else if (pthread->joiner != NULL) { /* Unlock the thread and remove the reference. */ diff --git a/lib/libkse/thread/thr_mutex_prioceiling.c b/lib/libkse/thread/thr_mutex_prioceiling.c index a78b5d1..c65270a 100644 --- a/lib/libkse/thread/thr_mutex_prioceiling.c +++ b/lib/libkse/thread/thr_mutex_prioceiling.c @@ -93,6 +93,7 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling) { int ret = 0; + int tmp; if ((mutex == NULL) || (*mutex == NULL)) ret = EINVAL; @@ -100,12 +101,15 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, ret = EINVAL; /* Lock the mutex: */ else if ((ret = pthread_mutex_lock(mutex)) == 0) { - /* Return the old ceiling and set the new ceiling: */ - *old_ceiling = (*mutex)->m_prio; + tmp = (*mutex)->m_prio; + /* Set the new ceiling: */ (*mutex)->m_prio = prioceiling; /* Unlock the mutex: */ ret = pthread_mutex_unlock(mutex); + + /* Return the old ceiling: */ + *old_ceiling = tmp; } return(ret); } diff --git a/lib/libkse/thread/thr_sigaction.c b/lib/libkse/thread/thr_sigaction.c index 2bef7f2..c4f5be8 100644 --- a/lib/libkse/thread/thr_sigaction.c +++ b/lib/libkse/thread/thr_sigaction.c @@ -42,9 +42,9 @@ int _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) { int ret = 0; - struct sigaction gact; + struct sigaction newact, oldact; struct pthread *curthread; - kse_critical_t crit; + kse_critical_t crit; /* Check if the signal number is out of range: */ if (sig < 1 || sig > _SIG_MAXSIG) { @@ -55,6 +55,9 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) if (!_kse_isthreaded()) return __sys_sigaction(sig, act, oact); + if (act) + newact = *act; + crit = _kse_critical_enter(); curthread = _get_curthread(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); @@ -64,17 +67,13 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) */ if (oact != NULL) { /* Return the existing signal action contents: */ - oact->sa_handler = _thread_sigact[sig - 1].sa_handler; - oact->sa_mask = _thread_sigact[sig - 1].sa_mask; - oact->sa_flags = _thread_sigact[sig - 1].sa_flags; + oldact = _thread_sigact[sig - 1]; } /* Check if a signal action was supplied: */ if (act != NULL) { /* Set the new signal handler: */ - _thread_sigact[sig - 1].sa_mask = act->sa_mask; - _thread_sigact[sig - 1].sa_flags = act->sa_flags; - _thread_sigact[sig - 1].sa_handler = act->sa_handler; + _thread_sigact[sig - 1] = newact; } /* @@ -82,30 +81,30 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) * in signal action: */ if (act != NULL && sig != SIGINFO) { - gact.sa_mask = act->sa_mask; - gact.sa_flags = SA_SIGINFO | act->sa_flags; + + newact.sa_flags |= SA_SIGINFO; /* * Check if the signal handler is being set to * the default or ignore handlers: */ - if (act->sa_handler == SIG_DFL || - act->sa_handler == SIG_IGN) - /* Specify the built in handler: */ - gact.sa_handler = act->sa_handler; - else + if (newact.sa_handler != SIG_DFL && + newact.sa_handler != SIG_IGN) { /* * Specify the thread kernel signal * handler: */ - gact.sa_handler = (void (*) ())_thr_sig_handler; - + newact.sa_handler = (void (*) ())_thr_sig_handler; + } /* Change the signal action in the kernel: */ - if (__sys_sigaction(sig, &gact, NULL) != 0) + if (__sys_sigaction(sig, &newact, NULL) != 0) ret = -1; } KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); + + if (oact != NULL) + *oact = oldact; } /* Return the completion status: */ diff --git a/lib/libkse/thread/thr_sigmask.c b/lib/libkse/thread/thr_sigmask.c index c8fcec8..3fd6df7 100644 --- a/lib/libkse/thread/thr_sigmask.c +++ b/lib/libkse/thread/thr_sigmask.c @@ -46,16 +46,21 @@ int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { struct pthread *curthread = _get_curthread(); + sigset_t oldset, newset; int ret; if (! _kse_isthreaded()) _kse_setthreaded(1); + if (set) + newset = *set; + THR_SCHED_LOCK(curthread, curthread); + ret = 0; if (oset != NULL) /* Return the current mask: */ - *oset = curthread->sigmask; + oldset = curthread->sigmask; /* Check if a new signal set was provided by the caller: */ if (set != NULL) { @@ -64,19 +69,19 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ - SIGSETOR(curthread->sigmask, *set); + SIGSETOR(curthread->sigmask, newset); break; /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ - SIGSETNAND(curthread->sigmask, *set); + SIGSETNAND(curthread->sigmask, newset); break; /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ - curthread->sigmask = *set; + curthread->sigmask = newset; break; /* Trap invalid actions: */ @@ -96,5 +101,8 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) _thr_sig_check_pending(curthread); } else THR_SCHED_UNLOCK(curthread, curthread); + + if (ret == 0 && oset != NULL) + *oset = oldset; return (ret); } diff --git a/lib/libkse/thread/thr_sigpending.c b/lib/libkse/thread/thr_sigpending.c index 1b9b502..1edf01f 100644 --- a/lib/libkse/thread/thr_sigpending.c +++ b/lib/libkse/thread/thr_sigpending.c @@ -46,6 +46,7 @@ _sigpending(sigset_t *set) { struct pthread *curthread = _get_curthread(); kse_critical_t crit; + sigset_t sigset; int ret = 0; /* Check for a null signal set pointer: */ @@ -59,12 +60,13 @@ _sigpending(sigset_t *set) crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, curthread->kseg); - *set = curthread->sigpend; + sigset = curthread->sigpend; KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); - SIGSETOR(*set, _thr_proc_sigpending); + SIGSETOR(sigset, _thr_proc_sigpending); KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); + *set = sigset; } /* Return the completion status: */ return (ret); diff --git a/lib/libkse/thread/thr_sigsuspend.c b/lib/libkse/thread/thr_sigsuspend.c index 8d087f5..869e3d9 100644 --- a/lib/libkse/thread/thr_sigsuspend.c +++ b/lib/libkse/thread/thr_sigsuspend.c @@ -43,20 +43,23 @@ int _sigsuspend(const sigset_t *set) { struct pthread *curthread = _get_curthread(); + sigset_t oldmask, newmask; int ret = -1; - sigset_t osigmask; if (!_kse_isthreaded()) return __sys_sigsuspend(set); /* Check if a new signal set was provided by the caller: */ if (set != NULL) { + newmask = *set; + THR_LOCK_SWITCH(curthread); /* Save current sigmask */ - memcpy(&osigmask, &curthread->sigmask, sizeof(osigmask)); + memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t)); + /* Change the caller's mask: */ - memcpy(&curthread->sigmask, set, sizeof(sigset_t)); + memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t)); THR_SET_STATE(curthread, PS_SIGSUSPEND); @@ -68,7 +71,7 @@ _sigsuspend(const sigset_t *set) THR_SCHED_LOCK(curthread, curthread); /* Restore the signal mask: */ - memcpy(&curthread->sigmask, &osigmask, sizeof(sigset_t)); + memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t)); THR_SCHED_UNLOCK(curthread, curthread); /* * signal mask is reloaded, need to check if there is diff --git a/lib/libpthread/thread/thr_attr_get_np.c b/lib/libpthread/thread/thr_attr_get_np.c index 4431824..e844acb 100644 --- a/lib/libpthread/thread/thr_attr_get_np.c +++ b/lib/libpthread/thread/thr_attr_get_np.c @@ -37,6 +37,7 @@ int _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) { struct pthread *curthread; + struct pthread_attr attr; int ret; if (pid == NULL || dst == NULL || *dst == NULL) @@ -45,9 +46,9 @@ _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst) curthread = _get_curthread(); if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0) return (ret); - - memcpy(*dst, &pid->attr, sizeof(struct pthread_attr)); + attr = pid->attr; _thr_ref_delete(curthread, pid); + memcpy(*dst, &attr, sizeof(struct pthread_attr)); return (0); } diff --git a/lib/libpthread/thread/thr_cancel.c b/lib/libpthread/thread/thr_cancel.c index 085f349..905891c 100644 --- a/lib/libpthread/thread/thr_cancel.c +++ b/lib/libpthread/thread/thr_cancel.c @@ -146,16 +146,12 @@ _pthread_setcancelstate(int state, int *oldstate) switch (state) { case PTHREAD_CANCEL_ENABLE: - if (oldstate != NULL) - *oldstate = ostate; curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE; if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0) need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DISABLE: - if (oldstate != NULL) - *oldstate = ostate; curthread->cancelflags |= PTHREAD_CANCEL_DISABLE; ret = 0; break; @@ -169,6 +165,9 @@ _pthread_setcancelstate(int state, int *oldstate) pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } + if (ret == 0 && oldstate != NULL) + *oldstate = ostate; + return (ret); } @@ -186,15 +185,11 @@ _pthread_setcanceltype(int type, int *oldtype) otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS; switch (type) { case PTHREAD_CANCEL_ASYNCHRONOUS: - if (oldtype != NULL) - *oldtype = otype; curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS; need_exit = checkcancel(curthread); ret = 0; break; case PTHREAD_CANCEL_DEFERRED: - if (oldtype != NULL) - *oldtype = otype; curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS; ret = 0; break; @@ -208,6 +203,9 @@ _pthread_setcanceltype(int type, int *oldtype) pthread_exit(PTHREAD_CANCELED); PANIC("cancel"); } + if (ret == 0 && oldtype != NULL) + *oldtype = otype; + return (ret); } diff --git a/lib/libpthread/thread/thr_getschedparam.c b/lib/libpthread/thread/thr_getschedparam.c index d00e498..ad8486c 100644 --- a/lib/libpthread/thread/thr_getschedparam.c +++ b/lib/libpthread/thread/thr_getschedparam.c @@ -42,7 +42,7 @@ _pthread_getschedparam(pthread_t pthread, int *policy, struct sched_param *param) { struct pthread *curthread = _get_curthread(); - int ret; + int ret, tmp; if ((param == NULL) || (policy == NULL)) /* Return an invalid argument error: */ @@ -55,8 +55,9 @@ _pthread_getschedparam(pthread_t pthread, int *policy, THR_SCHED_LOCK(curthread, curthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); - *policy = pthread->attr.sched_policy; + tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, curthread); + *policy = tmp; ret = 0; } /* Find the thread in the list of active threads. */ @@ -65,9 +66,10 @@ _pthread_getschedparam(pthread_t pthread, int *policy, THR_SCHED_LOCK(curthread, pthread); param->sched_priority = THR_BASE_PRIORITY(pthread->base_priority); - *policy = pthread->attr.sched_policy; + tmp = pthread->attr.sched_policy; THR_SCHED_UNLOCK(curthread, pthread); _thr_ref_delete(curthread, pthread); + *policy = tmp; } return (ret); } diff --git a/lib/libpthread/thread/thr_join.c b/lib/libpthread/thread/thr_join.c index d6add88..592aa3a 100644 --- a/lib/libpthread/thread/thr_join.c +++ b/lib/libpthread/thread/thr_join.c @@ -41,6 +41,7 @@ int _pthread_join(pthread_t pthread, void **thread_return) { struct pthread *curthread = _get_curthread(); + void *tmp; kse_critical_t crit; int ret = 0; @@ -80,9 +81,8 @@ _pthread_join(pthread_t pthread, void **thread_return) } else { /* Lock the target thread while checking its state. */ if (pthread->state == PS_DEAD) { - if (thread_return != NULL) - /* Return the thread's return value: */ - *thread_return = pthread->ret; + /* Return the thread's return value: */ + tmp = pthread->ret; /* Detach the thread. */ pthread->attr.flags |= PTHREAD_DETACHED; @@ -103,6 +103,8 @@ _pthread_join(pthread_t pthread, void **thread_return) /* Remove the reference. */ _thr_ref_delete(curthread, pthread); + if (thread_return != NULL) + *thread_return = tmp; } else if (pthread->joiner != NULL) { /* Unlock the thread and remove the reference. */ diff --git a/lib/libpthread/thread/thr_mutex_prioceiling.c b/lib/libpthread/thread/thr_mutex_prioceiling.c index a78b5d1..c65270a 100644 --- a/lib/libpthread/thread/thr_mutex_prioceiling.c +++ b/lib/libpthread/thread/thr_mutex_prioceiling.c @@ -93,6 +93,7 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int prioceiling, int *old_ceiling) { int ret = 0; + int tmp; if ((mutex == NULL) || (*mutex == NULL)) ret = EINVAL; @@ -100,12 +101,15 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex, ret = EINVAL; /* Lock the mutex: */ else if ((ret = pthread_mutex_lock(mutex)) == 0) { - /* Return the old ceiling and set the new ceiling: */ - *old_ceiling = (*mutex)->m_prio; + tmp = (*mutex)->m_prio; + /* Set the new ceiling: */ (*mutex)->m_prio = prioceiling; /* Unlock the mutex: */ ret = pthread_mutex_unlock(mutex); + + /* Return the old ceiling: */ + *old_ceiling = tmp; } return(ret); } diff --git a/lib/libpthread/thread/thr_sigaction.c b/lib/libpthread/thread/thr_sigaction.c index 2bef7f2..c4f5be8 100644 --- a/lib/libpthread/thread/thr_sigaction.c +++ b/lib/libpthread/thread/thr_sigaction.c @@ -42,9 +42,9 @@ int _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) { int ret = 0; - struct sigaction gact; + struct sigaction newact, oldact; struct pthread *curthread; - kse_critical_t crit; + kse_critical_t crit; /* Check if the signal number is out of range: */ if (sig < 1 || sig > _SIG_MAXSIG) { @@ -55,6 +55,9 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) if (!_kse_isthreaded()) return __sys_sigaction(sig, act, oact); + if (act) + newact = *act; + crit = _kse_critical_enter(); curthread = _get_curthread(); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); @@ -64,17 +67,13 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) */ if (oact != NULL) { /* Return the existing signal action contents: */ - oact->sa_handler = _thread_sigact[sig - 1].sa_handler; - oact->sa_mask = _thread_sigact[sig - 1].sa_mask; - oact->sa_flags = _thread_sigact[sig - 1].sa_flags; + oldact = _thread_sigact[sig - 1]; } /* Check if a signal action was supplied: */ if (act != NULL) { /* Set the new signal handler: */ - _thread_sigact[sig - 1].sa_mask = act->sa_mask; - _thread_sigact[sig - 1].sa_flags = act->sa_flags; - _thread_sigact[sig - 1].sa_handler = act->sa_handler; + _thread_sigact[sig - 1] = newact; } /* @@ -82,30 +81,30 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) * in signal action: */ if (act != NULL && sig != SIGINFO) { - gact.sa_mask = act->sa_mask; - gact.sa_flags = SA_SIGINFO | act->sa_flags; + + newact.sa_flags |= SA_SIGINFO; /* * Check if the signal handler is being set to * the default or ignore handlers: */ - if (act->sa_handler == SIG_DFL || - act->sa_handler == SIG_IGN) - /* Specify the built in handler: */ - gact.sa_handler = act->sa_handler; - else + if (newact.sa_handler != SIG_DFL && + newact.sa_handler != SIG_IGN) { /* * Specify the thread kernel signal * handler: */ - gact.sa_handler = (void (*) ())_thr_sig_handler; - + newact.sa_handler = (void (*) ())_thr_sig_handler; + } /* Change the signal action in the kernel: */ - if (__sys_sigaction(sig, &gact, NULL) != 0) + if (__sys_sigaction(sig, &newact, NULL) != 0) ret = -1; } KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); + + if (oact != NULL) + *oact = oldact; } /* Return the completion status: */ diff --git a/lib/libpthread/thread/thr_sigmask.c b/lib/libpthread/thread/thr_sigmask.c index c8fcec8..3fd6df7 100644 --- a/lib/libpthread/thread/thr_sigmask.c +++ b/lib/libpthread/thread/thr_sigmask.c @@ -46,16 +46,21 @@ int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { struct pthread *curthread = _get_curthread(); + sigset_t oldset, newset; int ret; if (! _kse_isthreaded()) _kse_setthreaded(1); + if (set) + newset = *set; + THR_SCHED_LOCK(curthread, curthread); + ret = 0; if (oset != NULL) /* Return the current mask: */ - *oset = curthread->sigmask; + oldset = curthread->sigmask; /* Check if a new signal set was provided by the caller: */ if (set != NULL) { @@ -64,19 +69,19 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) /* Block signals: */ case SIG_BLOCK: /* Add signals to the existing mask: */ - SIGSETOR(curthread->sigmask, *set); + SIGSETOR(curthread->sigmask, newset); break; /* Unblock signals: */ case SIG_UNBLOCK: /* Clear signals from the existing mask: */ - SIGSETNAND(curthread->sigmask, *set); + SIGSETNAND(curthread->sigmask, newset); break; /* Set the signal process mask: */ case SIG_SETMASK: /* Set the new mask: */ - curthread->sigmask = *set; + curthread->sigmask = newset; break; /* Trap invalid actions: */ @@ -96,5 +101,8 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) _thr_sig_check_pending(curthread); } else THR_SCHED_UNLOCK(curthread, curthread); + + if (ret == 0 && oset != NULL) + *oset = oldset; return (ret); } diff --git a/lib/libpthread/thread/thr_sigpending.c b/lib/libpthread/thread/thr_sigpending.c index 1b9b502..1edf01f 100644 --- a/lib/libpthread/thread/thr_sigpending.c +++ b/lib/libpthread/thread/thr_sigpending.c @@ -46,6 +46,7 @@ _sigpending(sigset_t *set) { struct pthread *curthread = _get_curthread(); kse_critical_t crit; + sigset_t sigset; int ret = 0; /* Check for a null signal set pointer: */ @@ -59,12 +60,13 @@ _sigpending(sigset_t *set) crit = _kse_critical_enter(); KSE_SCHED_LOCK(curthread->kse, curthread->kseg); - *set = curthread->sigpend; + sigset = curthread->sigpend; KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg); KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); - SIGSETOR(*set, _thr_proc_sigpending); + SIGSETOR(sigset, _thr_proc_sigpending); KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); _kse_critical_leave(crit); + *set = sigset; } /* Return the completion status: */ return (ret); diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c index 8d087f5..869e3d9 100644 --- a/lib/libpthread/thread/thr_sigsuspend.c +++ b/lib/libpthread/thread/thr_sigsuspend.c @@ -43,20 +43,23 @@ int _sigsuspend(const sigset_t *set) { struct pthread *curthread = _get_curthread(); + sigset_t oldmask, newmask; int ret = -1; - sigset_t osigmask; if (!_kse_isthreaded()) return __sys_sigsuspend(set); /* Check if a new signal set was provided by the caller: */ if (set != NULL) { + newmask = *set; + THR_LOCK_SWITCH(curthread); /* Save current sigmask */ - memcpy(&osigmask, &curthread->sigmask, sizeof(osigmask)); + memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t)); + /* Change the caller's mask: */ - memcpy(&curthread->sigmask, set, sizeof(sigset_t)); + memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t)); THR_SET_STATE(curthread, PS_SIGSUSPEND); @@ -68,7 +71,7 @@ _sigsuspend(const sigset_t *set) THR_SCHED_LOCK(curthread, curthread); /* Restore the signal mask: */ - memcpy(&curthread->sigmask, &osigmask, sizeof(sigset_t)); + memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t)); THR_SCHED_UNLOCK(curthread, curthread); /* * signal mask is reloaded, need to check if there is |