mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibCore: Protect ThreadData with a mutex in EventLoopImplementationUnix
`register_notifier()` and `unregister_notifier()` could be called from different threads modifying the same `ThreadData`.
This commit is contained in:
parent
bf0884c4ec
commit
b7cd606ff4
Notes:
github-actions[bot]
2025-11-02 21:44:25 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: b7cd606ff4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6494
Reviewed-by: https://github.com/R-Goc
Reviewed-by: https://github.com/trflynn89
1 changed files with 11 additions and 2 deletions
|
|
@ -240,7 +240,7 @@ struct ThreadData {
|
|||
|
||||
static ThreadData* for_thread(pthread_t thread_id)
|
||||
{
|
||||
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
|
||||
// NOTE: s_thread_data_lock is supposed to be held by the caller.
|
||||
return s_thread_data.get(thread_id).value_or(nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +267,8 @@ struct ThreadData {
|
|||
s_thread_data.remove(s_thread_id);
|
||||
}
|
||||
|
||||
Threading::Mutex mutex;
|
||||
|
||||
// Each thread has its own timers, notifiers and a wake pipe.
|
||||
TimeoutSet timeouts;
|
||||
|
||||
|
|
@ -328,6 +330,7 @@ void EventLoopImplementationUnix::wake()
|
|||
void EventLoopManagerUnix::wait_for_events(EventLoopImplementation::PumpMode mode)
|
||||
{
|
||||
auto& thread_data = ThreadData::the();
|
||||
Threading::MutexLocker locker(thread_data.mutex);
|
||||
|
||||
retry:
|
||||
bool has_pending_events = ThreadEventQueue::current().has_pending_events();
|
||||
|
|
@ -612,6 +615,7 @@ intptr_t EventLoopManagerUnix::register_timer(EventReceiver& object, int millise
|
|||
{
|
||||
VERIFY(milliseconds >= 0);
|
||||
auto& thread_data = ThreadData::the();
|
||||
Threading::MutexLocker locker(thread_data.mutex);
|
||||
auto timer = new EventLoopTimer;
|
||||
timer->owner_thread = s_thread_id;
|
||||
timer->owner = object;
|
||||
|
|
@ -625,9 +629,11 @@ intptr_t EventLoopManagerUnix::register_timer(EventReceiver& object, int millise
|
|||
void EventLoopManagerUnix::unregister_timer(intptr_t timer_id)
|
||||
{
|
||||
auto* timer = bit_cast<EventLoopTimer*>(timer_id);
|
||||
auto thread_data_ptr = ThreadData::for_thread(timer->owner_thread);
|
||||
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
|
||||
auto* thread_data_ptr = ThreadData::for_thread(timer->owner_thread);
|
||||
if (!thread_data_ptr)
|
||||
return;
|
||||
Threading::MutexLocker thread_data_content_locker(thread_data_ptr->mutex);
|
||||
auto& thread_data = *thread_data_ptr;
|
||||
auto expected = false;
|
||||
if (timer->is_being_deleted.compare_exchange_strong(expected, true, AK::MemoryOrder::memory_order_acq_rel)) {
|
||||
|
|
@ -640,6 +646,7 @@ void EventLoopManagerUnix::unregister_timer(intptr_t timer_id)
|
|||
void EventLoopManagerUnix::register_notifier(Notifier& notifier)
|
||||
{
|
||||
auto& thread_data = ThreadData::the();
|
||||
Threading::MutexLocker locker(thread_data.mutex);
|
||||
|
||||
thread_data.notifier_to_index.set(¬ifier, thread_data.poll_fds.size());
|
||||
thread_data.notifiers.append(¬ifier);
|
||||
|
|
@ -652,9 +659,11 @@ void EventLoopManagerUnix::register_notifier(Notifier& notifier)
|
|||
|
||||
void EventLoopManagerUnix::unregister_notifier(Notifier& notifier)
|
||||
{
|
||||
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
|
||||
auto* thread_data = ThreadData::for_thread(notifier.owner_thread());
|
||||
if (!thread_data)
|
||||
return;
|
||||
Threading::MutexLocker thread_data_content_locker(thread_data->mutex);
|
||||
|
||||
auto notifier_index = thread_data->notifier_to_index.take(¬ifier).release_value();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue