mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
libthr rtld locks: do not leak URWLOCK_READ_WAITERS into child
Since there is only the current thread in the child, no pending readers exist. Clear the bit, since it confuses future attempts to acquire write ownership of the rtld locks, due to URWLOCK_PREFER_READERS flag. To be future-proof, clear all state about pending writers and readers. PR: 271490 Reported and tested by: KJ Tsanaktsidis <kj@kjtsanaktsidis.id.au> Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D40178
This commit is contained in:
parent
54418f79fd
commit
6f49eafb05
|
@ -78,6 +78,8 @@ __FBSDID("$FreeBSD$");
|
|||
__weak_reference(_thr_atfork, _pthread_atfork);
|
||||
__weak_reference(_thr_atfork, pthread_atfork);
|
||||
|
||||
bool _thr_after_fork = false;
|
||||
|
||||
int
|
||||
_thr_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void (*child)(void))
|
||||
|
@ -243,7 +245,9 @@ thr_fork_impl(const struct thr_fork_args *a)
|
|||
_thr_signal_postfork_child();
|
||||
|
||||
if (was_threaded) {
|
||||
_thr_after_fork = true;
|
||||
_rtld_atfork_post(rtld_locks);
|
||||
_thr_after_fork = false;
|
||||
__thr_pshared_atfork_post();
|
||||
}
|
||||
_thr_setthreaded(0);
|
||||
|
|
|
@ -779,6 +779,8 @@ extern int _suspend_all_waiters __hidden;
|
|||
extern int _suspend_all_cycle __hidden;
|
||||
extern struct pthread *_single_thread __hidden;
|
||||
|
||||
extern bool _thr_after_fork __hidden;
|
||||
|
||||
/*
|
||||
* Function prototype definitions.
|
||||
*/
|
||||
|
|
|
@ -158,6 +158,17 @@ _thr_rtld_lock_release(void *lock)
|
|||
l = (struct rtld_lock *)lock;
|
||||
|
||||
state = l->lock.rw_state;
|
||||
if (__predict_false(_thr_after_fork)) {
|
||||
/*
|
||||
* After fork, only this thread is running, there is no
|
||||
* waiters. Keeping waiters recorded in rwlock breaks
|
||||
* wake logic.
|
||||
*/
|
||||
atomic_clear_int(&l->lock.rw_state,
|
||||
URWLOCK_WRITE_WAITERS | URWLOCK_READ_WAITERS);
|
||||
l->lock.rw_blocked_readers = 0;
|
||||
l->lock.rw_blocked_writers = 0;
|
||||
}
|
||||
if (_thr_rwlock_unlock(&l->lock) == 0) {
|
||||
if ((state & URWLOCK_WRITE_OWNER) == 0)
|
||||
curthread->rdlock_count--;
|
||||
|
|
Loading…
Reference in a new issue