From f4a56d7e61f6c54faf8230fde91280c56f871c5c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 30 Mar 2020 14:26:15 -0700 Subject: [PATCH] Enable thread-safety features in libdbus There are multiple SDL APIs that internally sink into dbus calls, e.g. battery status, thread priority. If those calls happen in different threads simultaneously it can result in dbus crashes. To abide by dbus's multithreading guidelines we must call dbus_threads_init_default() to enable dbus's internal locking mechanisms: https://dbus.freedesktop.org/doc/api/html/group__DBusThreads.html#gac7b8a7001befc3eaa8c6b043151008dc Additionally, access to a DBusMessage must be synchronized between threads. SDL was already abiding that guideline as the DBusMessage structs aren't shared. The following email from the dbus mailing list hints that arbitrating access to the DBusConnection on the SDL may also be required: https://lists.freedesktop.org/archives/dbus/2017-September/017306.html --- src/core/linux/SDL_dbus.c | 6 ++++++ src/core/linux/SDL_dbus.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index 8a279b474271a..02579aa305927 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -65,6 +65,7 @@ LoadDBUSSyms(void) SDL_DBUS_SYM(message_iter_get_arg_type); SDL_DBUS_SYM(message_iter_recurse); SDL_DBUS_SYM(message_unref); + SDL_DBUS_SYM(threads_init_default); SDL_DBUS_SYM(error_init); SDL_DBUS_SYM(error_is_set); SDL_DBUS_SYM(error_free); @@ -124,6 +125,11 @@ SDL_DBus_Init(void) return; /* oh well */ } + if (!dbus.threads_init_default()) { + is_dbus_available = SDL_FALSE; + return; + } + dbus.error_init(&err); /* session bus is required */ diff --git a/src/core/linux/SDL_dbus.h b/src/core/linux/SDL_dbus.h index 6967cc9b90182..9f77512aa1f7f 100644 --- a/src/core/linux/SDL_dbus.h +++ b/src/core/linux/SDL_dbus.h @@ -62,6 +62,7 @@ typedef struct SDL_DBusContext { int (*message_iter_get_arg_type)(DBusMessageIter *); void (*message_iter_recurse)(DBusMessageIter *, DBusMessageIter *); void (*message_unref)(DBusMessage *); + dbus_bool_t (*threads_init_default)(void); void (*error_init)(DBusError *); dbus_bool_t (*error_is_set)(const DBusError *); void (*error_free)(DBusError *);