summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2003-07-07 04:28:23 +0000
committerdavidxu <davidxu@FreeBSD.org>2003-07-07 04:28:23 +0000
commit8aa4e2d6856d1eed699b30ccca6163f8e501e183 (patch)
tree6539674ba4c0ff3018faf64006ac81eb9090ec5f /lib
parente95dd66c1f7fd662d47b34b5d83f1dcaa8b150e3 (diff)
downloadFreeBSD-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.c5
-rw-r--r--lib/libkse/thread/thr_cancel.c14
-rw-r--r--lib/libkse/thread/thr_getschedparam.c8
-rw-r--r--lib/libkse/thread/thr_join.c8
-rw-r--r--lib/libkse/thread/thr_mutex_prioceiling.c8
-rw-r--r--lib/libkse/thread/thr_sigaction.c35
-rw-r--r--lib/libkse/thread/thr_sigmask.c16
-rw-r--r--lib/libkse/thread/thr_sigpending.c6
-rw-r--r--lib/libkse/thread/thr_sigsuspend.c11
-rw-r--r--lib/libpthread/thread/thr_attr_get_np.c5
-rw-r--r--lib/libpthread/thread/thr_cancel.c14
-rw-r--r--lib/libpthread/thread/thr_getschedparam.c8
-rw-r--r--lib/libpthread/thread/thr_join.c8
-rw-r--r--lib/libpthread/thread/thr_mutex_prioceiling.c8
-rw-r--r--lib/libpthread/thread/thr_sigaction.c35
-rw-r--r--lib/libpthread/thread/thr_sigmask.c16
-rw-r--r--lib/libpthread/thread/thr_sigpending.c6
-rw-r--r--lib/libpthread/thread/thr_sigsuspend.c11
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
OpenPOWER on IntegriCloud