mirror of
git://git.musl-libc.org/musl
synced 2025-04-11 03:31:50 +00:00
reorder thread list unlink in pthread_exit after all locks
since the backend for LOCK() skips locking if single-threaded, it's unsafe to make the process appear single-threaded before the last use of lock. this fixes potential unsynchronized access to a linked list via __dl_thread_cleanup.
This commit is contained in:
parent
cabc36969b
commit
4d5aa20a94
@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *result)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we are committed to thread termination. Unlink
|
/* At this point we are committed to thread termination. */
|
||||||
* the thread from the list. This change will not be visible
|
|
||||||
* until the lock is released, which only happens after SYS_exit
|
|
||||||
* has been called, via the exit futex address pointing at the lock. */
|
|
||||||
libc.threads_minus_1--;
|
|
||||||
self->next->prev = self->prev;
|
|
||||||
self->prev->next = self->next;
|
|
||||||
self->prev = self->next = self;
|
|
||||||
|
|
||||||
/* Process robust list in userspace to handle non-pshared mutexes
|
/* Process robust list in userspace to handle non-pshared mutexes
|
||||||
* and the detached thread case where the robust list head will
|
* and the detached thread case where the robust list head will
|
||||||
@ -121,6 +114,16 @@ _Noreturn void __pthread_exit(void *result)
|
|||||||
__do_orphaned_stdio_locks();
|
__do_orphaned_stdio_locks();
|
||||||
__dl_thread_cleanup();
|
__dl_thread_cleanup();
|
||||||
|
|
||||||
|
/* Last, unlink thread from the list. This change will not be visible
|
||||||
|
* until the lock is released, which only happens after SYS_exit
|
||||||
|
* has been called, via the exit futex address pointing at the lock.
|
||||||
|
* This needs to happen after any possible calls to LOCK() that might
|
||||||
|
* skip locking if libc.threads_minus_1 is zero. */
|
||||||
|
libc.threads_minus_1--;
|
||||||
|
self->next->prev = self->prev;
|
||||||
|
self->prev->next = self->next;
|
||||||
|
self->prev = self->next = self;
|
||||||
|
|
||||||
/* This atomic potentially competes with a concurrent pthread_detach
|
/* This atomic potentially competes with a concurrent pthread_detach
|
||||||
* call; the loser is responsible for freeing thread resources. */
|
* call; the loser is responsible for freeing thread resources. */
|
||||||
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
|
int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
|
||||||
|
Loading…
Reference in New Issue
Block a user