From 37acdc9ba742db96e94b89da0374e003d7b2e46d Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Sun, 6 Aug 2023 01:42:51 -0500 Subject: [PATCH] LibAudio: Unlock the mutex in PulseAudioContext::instance() before exit The mutex used to protect from multiple threads creating PulseAudio contexts simultaneously could remain locked when an application exited. The static variables' destructors could be called on the main thread while another thread is running `PulseAudioContext::instance()` and synchronously connecting to a PulseAudio daemon. This would cause an assertion in Mutex that it is unlocked upon its destructor being called. By creating a static `ScopeGuard` that locks and immediately unlocks the mutex, we can ensure that the main thread waits for the connection to succeed or fail. In most cases, this will not take long, but if the connection is timing out, it could take a matter of seconds. --- Userland/Libraries/LibAudio/PulseAudioWrappers.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Userland/Libraries/LibAudio/PulseAudioWrappers.cpp b/Userland/Libraries/LibAudio/PulseAudioWrappers.cpp index 0b7f336f08..2eba33d199 100644 --- a/Userland/Libraries/LibAudio/PulseAudioWrappers.cpp +++ b/Userland/Libraries/LibAudio/PulseAudioWrappers.cpp @@ -16,6 +16,13 @@ ErrorOr> PulseAudioContext::instance() // Use a weak pointer to allow the context to be shut down if we stop outputting audio. static WeakPtr the_instance; static Threading::Mutex instantiation_mutex; + // Lock and unlock the mutex to ensure that the mutex is fully unlocked at application + // exit. + atexit([]() { + instantiation_mutex.lock(); + instantiation_mutex.unlock(); + }); + auto instantiation_locker = Threading::MutexLocker(instantiation_mutex); RefPtr strong_instance_pointer = the_instance.strong_ref();