diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2023-05-20 08:11:54 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2023-05-29 03:20:42 +0000 |
| commit | 5b45cd83c44edb9386eed1155acd3c52f36bf12c (patch) | |
| tree | f2561dcc223f9c3bda6dd01aeee272a244df00bd | |
| parent | 3ffa7eff2275de05a3defeef859902a66f1d3135 (diff) | |
| download | src-5b45cd83c44edb9386eed1155acd3c52f36bf12c.tar.gz src-5b45cd83c44edb9386eed1155acd3c52f36bf12c.zip | |
libthr rtld locks: do not leak URWLOCK_READ_WAITERS into child
PR: 271490
(cherry picked from commit 6f49eafb056cfa0703dfc97a731cabe4ed2596b8)
| -rw-r--r-- | lib/libthr/thread/thr_fork.c | 4 | ||||
| -rw-r--r-- | lib/libthr/thread/thr_private.h | 2 | ||||
| -rw-r--r-- | lib/libthr/thread/thr_rtld.c | 11 |
3 files changed, 17 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index 9861e93c427d..341afc2b06ec 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -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); diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 0e88c6711817..910de374accf 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -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. */ diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 1967ea14859d..fe4fb7ae0602 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -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--; |
