From 920f47073582a8367de796817ccebbf0735d0740 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Wed, 5 Jun 2024 10:49:31 +0200 Subject: [PATCH] LibCore: Fix some thread-related memory/object leaks --- .../LibCore/EventLoopImplementationUnix.cpp | 26 ++++++++++++++----- .../Libraries/LibCore/ThreadEventQueue.cpp | 20 ++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp b/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp index 59154c2e762..47cc8f7838d 100644 --- a/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp +++ b/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp @@ -26,10 +26,12 @@ namespace { struct ThreadData; class TimeoutSet; -HashMap> s_thread_data; +HashMap s_thread_data; +pthread_key_t s_thread_key; static pthread_rwlock_t s_thread_data_lock_impl; static pthread_rwlock_t* s_thread_data_lock = nullptr; thread_local pthread_t s_thread_id; +thread_local OwnPtr s_this_thread_data; short notification_type_to_poll_events(NotificationType type) { @@ -221,21 +223,24 @@ struct ThreadData { if (!s_thread_data_lock) { pthread_rwlock_init(&s_thread_data_lock_impl, nullptr); s_thread_data_lock = &s_thread_data_lock_impl; + pthread_key_create(&s_thread_key, [](void*) { + s_this_thread_data.clear(); + }); } if (s_thread_id == 0) s_thread_id = pthread_self(); ThreadData* data = nullptr; - pthread_rwlock_rdlock(&*s_thread_data_lock); - if (!s_thread_data.contains(s_thread_id)) { + if (!s_this_thread_data) { data = new ThreadData; - pthread_rwlock_unlock(&*s_thread_data_lock); + s_this_thread_data = adopt_own(*data); + pthread_rwlock_wrlock(&*s_thread_data_lock); - s_thread_data.set(s_thread_id, adopt_own(*data)); + s_thread_data.set(s_thread_id, s_this_thread_data.ptr()); + pthread_rwlock_unlock(&*s_thread_data_lock); } else { - data = s_thread_data.get(s_thread_id).value(); + data = s_this_thread_data.ptr(); } - pthread_rwlock_unlock(&*s_thread_data_lock); return *data; } @@ -253,6 +258,13 @@ struct ThreadData { initialize_wake_pipe(); } + ~ThreadData() + { + pthread_rwlock_wrlock(&*s_thread_data_lock); + s_thread_data.remove(s_thread_id); + pthread_rwlock_unlock(&*s_thread_data_lock); + } + void initialize_wake_pipe() { if (wake_pipe_fds[0] != -1) diff --git a/Userland/Libraries/LibCore/ThreadEventQueue.cpp b/Userland/Libraries/LibCore/ThreadEventQueue.cpp index a6fbe30dccc..b500079f02e 100644 --- a/Userland/Libraries/LibCore/ThreadEventQueue.cpp +++ b/Userland/Libraries/LibCore/ThreadEventQueue.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace Core { @@ -39,15 +40,24 @@ struct ThreadEventQueue::Private { bool warned_promise_count { false }; }; -static thread_local ThreadEventQueue* s_current_thread_event_queue; +static pthread_key_t s_current_thread_event_queue_key; +static pthread_once_t s_current_thread_event_queue_key_once = PTHREAD_ONCE_INIT; ThreadEventQueue& ThreadEventQueue::current() { - if (!s_current_thread_event_queue) { - // FIXME: Don't leak these. - s_current_thread_event_queue = new ThreadEventQueue; + pthread_once(&s_current_thread_event_queue_key_once, [] { + pthread_key_create(&s_current_thread_event_queue_key, [](void* value) { + if (value) + delete static_cast(value); + }); + }); + + auto* ptr = static_cast(pthread_getspecific(s_current_thread_event_queue_key)); + if (!ptr) { + ptr = new ThreadEventQueue; + pthread_setspecific(s_current_thread_event_queue_key, ptr); } - return *s_current_thread_event_queue; + return *ptr; } ThreadEventQueue::ThreadEventQueue()