mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
make thread killlock async-signal-safe for pthread_kill
pthread_kill is required to be AS-safe. that requirement can't be met if the target thread's killlock can be taken in contexts where application-installed signal handlers can run. block signals around use of this lock in all pthread_* functions which target a tid, and reorder blocking/unblocking of signals in pthread_exit so that they're blocked whenever the killlock is held.
This commit is contained in:
parent
0a005f499c
commit
7cc9496a18
5 changed files with 18 additions and 5 deletions
|
@ -72,12 +72,13 @@ _Noreturn void __pthread_exit(void *result)
|
|||
/* 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
|
||||
|
@ -85,8 +86,8 @@ _Noreturn void __pthread_exit(void *result)
|
|||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param *restrict param)
|
||||
{
|
||||
int r;
|
||||
sigset_t set;
|
||||
__block_app_sigs(&set);
|
||||
LOCK(t->killlock);
|
||||
if (!t->tid) {
|
||||
r = ESRCH;
|
||||
|
@ -14,5 +16,6 @@ int pthread_getschedparam(pthread_t t, int *restrict policy, struct sched_param
|
|||
}
|
||||
}
|
||||
UNLOCK(t->killlock);
|
||||
__restore_sigs(&set);
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue