mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibThreading: Fix data race in RWLock::unlock()
The generic unlock() wrote to m_write_locked from every thread regardless of whether a read or write lock was held. When multiple threads held concurrent read locks, their unlock() calls would race on the non-atomic m_write_locked and m_read_locked_with_write_lock fields. Split unlock() into unlock_read() and unlock_write() so that read unlocks never touch the write-lock tracking fields. The RWLockLocker template dispatches at compile time based on LockMode.
This commit is contained in:
committed by
Andreas Kling
parent
8a6d902d4c
commit
656a84e180
Notes:
github-actions[bot]
2026-03-07 12:11:04 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/656a84e180b Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8304
@@ -180,7 +180,7 @@ StrongEventLoopReference::StrongEventLoopReference(WeakEventLoopReference& event
|
||||
|
||||
StrongEventLoopReference::~StrongEventLoopReference()
|
||||
{
|
||||
m_event_loop_weak->m_lock.unlock();
|
||||
m_event_loop_weak->m_lock.unlock_read();
|
||||
}
|
||||
|
||||
bool StrongEventLoopReference::is_alive() const
|
||||
|
||||
@@ -32,7 +32,8 @@ public:
|
||||
void lock_read();
|
||||
void lock_write();
|
||||
|
||||
void unlock();
|
||||
void unlock_read();
|
||||
void unlock_write();
|
||||
|
||||
private:
|
||||
pthread_rwlock_t m_rwlock;
|
||||
@@ -63,7 +64,10 @@ public:
|
||||
|
||||
ALWAYS_INLINE void unlock()
|
||||
{
|
||||
m_lock.unlock();
|
||||
if constexpr (mode == LockMode::Read)
|
||||
m_lock.unlock_read();
|
||||
else
|
||||
m_lock.unlock_write();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void lock()
|
||||
@@ -96,13 +100,19 @@ ALWAYS_INLINE void RWLock::lock_write()
|
||||
m_write_locked = true;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void RWLock::unlock()
|
||||
ALWAYS_INLINE void RWLock::unlock_read()
|
||||
{
|
||||
if (m_read_locked_with_write_lock) {
|
||||
m_read_locked_with_write_lock = false;
|
||||
return;
|
||||
}
|
||||
pthread_rwlock_unlock(&m_rwlock);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void RWLock::unlock_write()
|
||||
{
|
||||
m_write_locked = false;
|
||||
auto needs_unlock = !m_read_locked_with_write_lock;
|
||||
m_read_locked_with_write_lock = false;
|
||||
if (needs_unlock)
|
||||
pthread_rwlock_unlock(&m_rwlock);
|
||||
pthread_rwlock_unlock(&m_rwlock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user