dbus: Wrap init in a spinlock. This prevents a race if two threads that need d-bus try to init it at the same time. Note that SDL_Init will likely handle this from a single thread at startup, but there are places outside of init where one might trigger D-Bus init, like setting thread priority (a common first thing for a new thread to do) resulting in SDL trying to use RTKit. Fixes #4587.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c
index 9b22f78..e83da80 100644
--- a/src/core/linux/SDL_dbus.c
+++ b/src/core/linux/SDL_dbus.c
@@ -20,6 +20,7 @@
*/
#include "../../SDL_internal.h"
#include "SDL_dbus.h"
+#include "SDL_atomic.h"
#if SDL_USE_LIBDBUS
/* we never link directly to libdbus. */
@@ -113,8 +114,12 @@ LoadDBUSLibrary(void)
return retval;
}
-void
-SDL_DBus_Init(void)
+
+static SDL_SpinLock spinlock_dbus_init = 0;
+
+/* you must hold spinlock_dbus_init before calling this! */
+static void
+SDL_DBus_Init_Spinlocked(void)
{
static SDL_bool is_dbus_available = SDL_TRUE;
if (!is_dbus_available) {
@@ -157,6 +162,14 @@ SDL_DBus_Init(void)
}
void
+SDL_DBus_Init(void)
+{
+ SDL_AtomicLock(&spinlock_dbus_init); /* make sure two threads can't init at same time, since this can happen before SDL_Init. */
+ SDL_DBus_Init_Spinlocked();
+ SDL_AtomicUnlock(&spinlock_dbus_init);
+}
+
+void
SDL_DBus_Quit(void)
{
if (dbus.system_conn) {