/* Access to target the exiting thread with syscalls that use
* its kernel tid is controlled by killlock. For detached threads,
* any use past this point would have undefined behavior, but for
- * joinable threads it's a valid usage that must be handled. */
+ * joinable threads it's a valid usage that must be handled.
+ * Signals must be blocked since pthread_kill must be AS-safe. */
+ __block_app_sigs(&set);
LOCK(self->killlock);
- /* The thread list lock must be AS-safe, and thus requires
- * application signals to be blocked before it can be taken. */
- __block_app_sigs(&set);
+ /* The thread list lock must be AS-safe, and thus depends on
+ * application signals being blocked above. */
__tl_lock();
/* If this is the only thread in the list, don't proceed with
* signal state to prepare for exit to call atexit handlers. */
if (self->next == self) {
__tl_unlock();
- __restore_sigs(&set);
UNLOCK(self->killlock);
+ __restore_sigs(&set);
exit(0);
}
int pthread_kill(pthread_t t, int sig)
{
int r;
+ sigset_t set;
+ __block_app_sigs(&set);
LOCK(t->killlock);
r = t->tid ? -__syscall(SYS_tkill, t->tid, sig)
: (sig+0U >= _NSIG ? EINVAL : 0);
UNLOCK(t->killlock);
+ __restore_sigs(&set);
return r;
}
int pthread_setschedparam(pthread_t t, int policy, const struct sched_param *param)
{
int r;
+ sigset_t set;
+ __block_app_sigs(&set);
LOCK(t->killlock);
r = !t->tid ? ESRCH : -__syscall(SYS_sched_setscheduler, t->tid, policy, param);
UNLOCK(t->killlock);
+ __restore_sigs(&set);
return r;
}
int pthread_setschedprio(pthread_t t, int prio)
{
int r;
+ sigset_t set;
+ __block_app_sigs(&set);
LOCK(t->killlock);
r = !t->tid ? ESRCH : -__syscall(SYS_sched_setparam, t->tid, &prio);
UNLOCK(t->killlock);
+ __restore_sigs(&set);
return r;
}