From 5454573e2d7d5f70b96185998e9d27d919bdfeed Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 20 Jan 2026 17:08:20 -0800 Subject: [PATCH] Retain the dbus reply when getting string results The string result points at memory in the reply, so we can't unref that until the string is no longer needed. Fixes https://github.com/libsdl-org/SDL/issues/14839 --- src/core/linux/SDL_dbus.c | 103 +++++++++++++++++++------------- src/core/linux/SDL_dbus.h | 14 +++-- src/core/linux/SDL_fcitx.c | 2 +- src/core/linux/SDL_ibus.c | 8 ++- src/core/linux/SDL_threadprio.c | 24 ++++---- src/power/linux/SDL_syspower.c | 33 +++++----- 6 files changed, 108 insertions(+), 76 deletions(-) diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index a53c1abebe..3b7aa3682f 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -73,6 +73,7 @@ static bool LoadDBUSSyms(void) SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, int), connection_read_write); SDL_DBUS_SYM(dbus_bool_t (*)(DBusConnection *, int), connection_read_write_dispatch); SDL_DBUS_SYM(DBusDispatchStatus (*)(DBusConnection *), connection_dispatch); + SDL_DBUS_SYM(dbus_bool_t (*)(int), type_is_fixed); SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *, const char *), message_is_signal); SDL_DBUS_SYM(dbus_bool_t (*)(DBusMessage *, const char *), message_has_path); SDL_DBUS_SYM(DBusMessage *(*)(const char *, const char *, const char *, const char *), message_new_method_call); @@ -229,7 +230,7 @@ SDL_DBusContext *SDL_DBus_GetContext(void) return (dbus_handle && dbus.session_conn) ? &dbus : NULL; } -static bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) +static bool SDL_DBus_CallMethodInternal(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *method, va_list ap) { bool result = false; @@ -261,7 +262,11 @@ static bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) { result = true; } - dbus.message_unref(reply); + if (save_reply) { + *save_reply = reply; + } else { + dbus.message_unref(reply); + } } } va_end(ap_reply); @@ -272,22 +277,22 @@ static bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, return result; } -bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *method, ...) { bool result; va_list ap; va_start(ap, method); - result = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap); + result = SDL_DBus_CallMethodInternal(conn, save_reply, node, path, interface, method, ap); va_end(ap); return result; } -bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallMethod(DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *method, ...) { bool result; va_list ap; va_start(ap, method); - result = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap); + result = SDL_DBus_CallMethodInternal(dbus.session_conn, save_reply, node, path, interface, method, ap); va_end(ap); return result; } @@ -314,31 +319,6 @@ static bool SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *no return result; } -static bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *msg, const int expectedtype, void *result) -{ - bool retval = false; - - DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); - if (reply) { - DBusMessageIter iter, actual_iter; - dbus.message_iter_init(reply, &iter); - if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) { - dbus.message_iter_recurse(&iter, &actual_iter); - } else { - actual_iter = iter; - } - - if (dbus.message_iter_get_arg_type(&actual_iter) == expectedtype) { - dbus.message_iter_get_basic(&actual_iter, result); - retval = true; - } - - dbus.message_unref(reply); - } - - return retval; -} - bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) { bool result; @@ -359,7 +339,40 @@ bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *int return result; } -bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) +static bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage **save_reply, DBusMessage *msg, const int expectedtype, void *result) +{ + bool retval = false; + + // Make sure we're not looking up strings here, otherwise we'd have to save and return the reply + SDL_assert(save_reply == NULL || *save_reply == NULL); + SDL_assert(save_reply != NULL || dbus.type_is_fixed(expectedtype)); + + DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); + if (reply) { + DBusMessageIter iter, actual_iter; + dbus.message_iter_init(reply, &iter); + if (dbus.message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) { + dbus.message_iter_recurse(&iter, &actual_iter); + } else { + actual_iter = iter; + } + + if (dbus.message_iter_get_arg_type(&actual_iter) == expectedtype) { + dbus.message_iter_get_basic(&actual_iter, result); + retval = true; + } + + if (save_reply) { + *save_reply = reply; + } else { + dbus.message_unref(reply); + } + } + + return retval; +} + +bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) { bool retval = false; @@ -367,7 +380,7 @@ bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get"); if (msg) { if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) { - retval = SDL_DBus_CallWithBasicReply(conn, msg, expectedtype, result); + retval = SDL_DBus_CallWithBasicReply(conn, save_reply, msg, expectedtype, result); } dbus.message_unref(msg); } @@ -376,9 +389,18 @@ bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, return retval; } -bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) +bool SDL_DBus_QueryProperty(DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) { - return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result); + return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, save_reply, node, path, interface, property, expectedtype, result); +} + +void SDL_DBus_FreeReply(DBusMessage **saved_reply) +{ + DBusMessage *reply = *saved_reply; + if (reply) { + dbus.message_unref(reply); + *saved_reply = NULL; + } } void SDL_DBus_ScreensaverTickle(void) @@ -473,7 +495,7 @@ bool SDL_DBus_ScreensaverInhibit(bool inhibit) DBusMessage *msg; bool result = false; const char *key = "reason"; - const char *reply = NULL; + const char *reply_path = NULL; const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME); if (!reason || !reason[0]) { reason = default_inhibit_reason; @@ -497,11 +519,12 @@ bool SDL_DBus_ScreensaverInhibit(bool inhibit) return false; } - if (SDL_DBus_CallWithBasicReply(dbus.session_conn, msg, DBUS_TYPE_OBJECT_PATH, &reply)) { - inhibit_handle = SDL_strdup(reply); + DBusMessage *reply = NULL; + if (SDL_DBus_CallWithBasicReply(dbus.session_conn, &reply, msg, DBUS_TYPE_OBJECT_PATH, &reply_path)) { + inhibit_handle = SDL_strdup(reply_path); result = true; } - + SDL_DBus_FreeReply(&reply); dbus.message_unref(msg); return result; } else { @@ -523,7 +546,7 @@ bool SDL_DBus_ScreensaverInhibit(bool inhibit) reason = default_inhibit_reason; } - if (!SDL_DBus_CallMethod(bus_name, path, interface, "Inhibit", + if (!SDL_DBus_CallMethod(NULL, bus_name, path, interface, "Inhibit", DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID, DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { return false; diff --git a/src/core/linux/SDL_dbus.h b/src/core/linux/SDL_dbus.h index ca2c96abf0..83b11367c0 100644 --- a/src/core/linux/SDL_dbus.h +++ b/src/core/linux/SDL_dbus.h @@ -64,6 +64,7 @@ typedef struct SDL_DBusContext dbus_bool_t (*connection_read_write)(DBusConnection *, int); dbus_bool_t (*connection_read_write_dispatch)(DBusConnection *, int); DBusDispatchStatus (*connection_dispatch)(DBusConnection *); + dbus_bool_t (*type_is_fixed)(int); dbus_bool_t (*message_is_signal)(DBusMessage *, const char *, const char *); dbus_bool_t (*message_has_path)(DBusMessage *, const char *); DBusMessage *(*message_new_method_call)(const char *, const char *, const char *, const char *); @@ -100,14 +101,19 @@ extern void SDL_DBus_Quit(void); extern SDL_DBusContext *SDL_DBus_GetContext(void); // These use the built-in Session connection. -extern bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_CallMethod(DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *method, ...); extern bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...); -extern bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); +// save_reply must be non-NULL if it's a string property +extern bool SDL_DBus_QueryProperty(DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); // These use whatever connection you like. -extern bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *method, ...); extern bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); -extern bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); +// save_reply must be non-NULL if it's a string property +extern bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); + +// Used to free any reply returned from SDL_DBus_CallMethod() and SDL_DBus_QueryProperty() +extern void SDL_DBus_FreeReply(DBusMessage **saved_reply); extern void SDL_DBus_ScreensaverTickle(void); extern bool SDL_DBus_ScreensaverInhibit(bool inhibit); diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index d1222f76bd..d47b44e86f 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -370,7 +370,7 @@ bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) return false; } - if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent", + if (SDL_DBus_CallMethod(NULL, FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent", DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID, DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) { if (handled) { diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 0b9873445f..e018d10427 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -426,6 +426,7 @@ static void SDLCALL IBus_SetCapabilities(void *data, const char *name, const cha static bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) { const char *client_name = "SDL3_Application"; + DBusMessage *reply = NULL; const char *path = NULL; bool result = false; DBusObjectPathVTable ibus_vtable; @@ -442,7 +443,7 @@ static bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) ibus_input_interface = IBUS_PORTAL_INPUT_INTERFACE; ibus_conn = dbus->session_conn; - result = SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext", + result = SDL_DBus_CallMethodOnConnection(ibus_conn, &reply, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext", DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); if (!result) { @@ -465,7 +466,7 @@ static bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) dbus->connection_flush(ibus_conn); - result = SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext", + result = SDL_DBus_CallMethodOnConnection(ibus_conn, &reply, ibus_service, IBUS_PATH, ibus_interface, "CreateInputContext", DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); } else { @@ -483,6 +484,7 @@ static bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus, NULL); dbus->connection_flush(ibus_conn); } + SDL_DBus_FreeReply(&reply); SDL_Window *window = SDL_GetKeyboardFocus(); if (SDL_TextInputActive(window)) { @@ -669,7 +671,7 @@ bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) if (!down) { mods |= (1 << 30); // IBUS_RELEASE_MASK } - if (!SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "ProcessKeyEvent", + if (!SDL_DBus_CallMethodOnConnection(ibus_conn, NULL, ibus_service, input_ctx_path, ibus_input_interface, "ProcessKeyEvent", DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID, DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) { result = 0; diff --git a/src/core/linux/SDL_threadprio.c b/src/core/linux/SDL_threadprio.c index 2085378671..68b11911a1 100644 --- a/src/core/linux/SDL_threadprio.c +++ b/src/core/linux/SDL_threadprio.c @@ -70,7 +70,7 @@ static Sint64 rtkit_max_rttime_usec = 200000; static bool realtime_portal_supported(DBusConnection *conn) { Sint64 res; - return SDL_DBus_QueryPropertyOnConnection(conn, XDG_PORTAL_DBUS_NODE, XDG_PORTAL_DBUS_PATH, XDG_PORTAL_DBUS_INTERFACE, + return SDL_DBus_QueryPropertyOnConnection(conn, NULL, XDG_PORTAL_DBUS_NODE, XDG_PORTAL_DBUS_PATH, XDG_PORTAL_DBUS_INTERFACE, "RTTimeUSecMax", DBUS_TYPE_INT64, &res); } @@ -111,19 +111,19 @@ static void rtkit_initialize(void) dbus_conn = get_rtkit_dbus_connection(); // Try getting minimum nice level: this is often greater than PRIO_MIN (-20). - if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MinNiceLevel", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, NULL, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MinNiceLevel", DBUS_TYPE_INT32, &rtkit_min_nice_level)) { rtkit_min_nice_level = -20; } // Try getting maximum realtime priority: this can be less than the POSIX default (99). - if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MaxRealtimePriority", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, NULL, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MaxRealtimePriority", DBUS_TYPE_INT32, &rtkit_max_realtime_priority)) { rtkit_max_realtime_priority = 99; } // Try getting maximum rttime allowed by rtkit: exceeding this value will result in SIGKILL - if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "RTTimeUSecMax", + if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, NULL, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "RTTimeUSecMax", DBUS_TYPE_INT64, &rtkit_max_rttime_usec)) { rtkit_max_rttime_usec = 200000; } @@ -202,10 +202,10 @@ static bool rtkit_setpriority_nice(pid_t thread, int nice_level) nice = rtkit_min_nice_level; } - if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, - rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadHighPriorityWithPID", - DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_INT32, &nice, DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID)) { + if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, NULL, + rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadHighPriorityWithPID", + DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_INT32, &nice, DBUS_TYPE_INVALID, + DBUS_TYPE_INVALID)) { return false; } return true; @@ -233,10 +233,10 @@ static bool rtkit_setpriority_realtime(pid_t thread, int rt_priority) // go through to determine whether it really needs to fail or not. rtkit_initialize_realtime_thread(); - if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, - rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadRealtimeWithPID", - DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_UINT32, &priority, DBUS_TYPE_INVALID, - DBUS_TYPE_INVALID)) { + if (!dbus_conn || !SDL_DBus_CallMethodOnConnection(dbus_conn, NULL, + rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadRealtimeWithPID", + DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_UINT32, &priority, DBUS_TYPE_INVALID, + DBUS_TYPE_INVALID)) { return false; } return true; diff --git a/src/power/linux/SDL_syspower.c b/src/power/linux/SDL_syspower.c index dc87f88a90..88e7b481ec 100644 --- a/src/power/linux/SDL_syspower.c +++ b/src/power/linux/SDL_syspower.c @@ -536,17 +536,17 @@ static void check_upower_device(DBusConnection *conn, const char *path, SDL_Powe Sint64 si64 = 0; double d = 0.0; - if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Type", DBUS_TYPE_UINT32, &ui32)) { + if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Type", DBUS_TYPE_UINT32, &ui32)) { return; // Don't know _what_ we're looking at. Give up on it. } else if (ui32 != 2) { // 2==Battery return; // we don't care about UPS and such. - } else if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "PowerSupply", DBUS_TYPE_BOOLEAN, &ui32)) { + } else if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "PowerSupply", DBUS_TYPE_BOOLEAN, &ui32)) { return; } else if (!ui32) { return; // we don't care about random devices with batteries, like wireless controllers, etc } - if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "IsPresent", DBUS_TYPE_BOOLEAN, &ui32)) { + if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "IsPresent", DBUS_TYPE_BOOLEAN, &ui32)) { return; } if (!ui32) { @@ -555,9 +555,11 @@ static void check_upower_device(DBusConnection *conn, const char *path, SDL_Powe /* Get updated information on the battery status * This can occasionally fail, and we'll just return slightly stale data in that case */ - SDL_DBus_CallMethodOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Refresh", DBUS_TYPE_INVALID, DBUS_TYPE_INVALID); + SDL_DBus_CallMethodOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Refresh", + DBUS_TYPE_INVALID, + DBUS_TYPE_INVALID); - if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "State", DBUS_TYPE_UINT32, &ui32)) { + if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "State", DBUS_TYPE_UINT32, &ui32)) { st = SDL_POWERSTATE_UNKNOWN; // uh oh } else if (ui32 == 1) { // 1 == charging st = SDL_POWERSTATE_CHARGING; @@ -578,14 +580,14 @@ static void check_upower_device(DBusConnection *conn, const char *path, SDL_Powe } } - if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Percentage", DBUS_TYPE_DOUBLE, &d)) { + if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "Percentage", DBUS_TYPE_DOUBLE, &d)) { pct = -1; // some old/cheap batteries don't set this property. } else { pct = (int)d; pct = (pct > 100) ? 100 : pct; // clamp between 0%, 100% } - if (!SDL_DBus_QueryPropertyOnConnection(conn, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "TimeToEmpty", DBUS_TYPE_INT64, &si64)) { + if (!SDL_DBus_QueryPropertyOnConnection(conn, NULL, UPOWER_DBUS_NODE, path, UPOWER_DEVICE_DBUS_INTERFACE, "TimeToEmpty", DBUS_TYPE_INT64, &si64)) { secs = -1; } else { secs = (int)si64; @@ -620,6 +622,7 @@ bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *state, int *s #ifdef SDL_USE_LIBDBUS SDL_DBusContext *dbus = SDL_DBus_GetContext(); + DBusMessage *reply = NULL; char **paths = NULL; char *path = NULL; int i, numpaths = 0; @@ -628,22 +631,20 @@ bool SDL_GetPowerInfo_Linux_org_freedesktop_upower(SDL_PowerState *state, int *s return false; // try a different approach than UPower. } - if (SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "GetDisplayDevice", DBUS_TYPE_INVALID, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { + if (SDL_DBus_CallMethodOnConnection(dbus->system_conn, &reply, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "GetDisplayDevice", + DBUS_TYPE_INVALID, + DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { result = true; // Clearly we can use this interface. *state = SDL_POWERSTATE_NO_BATTERY; // assume we're just plugged in. *seconds = -1; *percent = -1; - // Make a copy of the path before making more dbus calls - path = SDL_strdup(path); - if (!path) { - // Out of memory, try to do something else - return false; - } check_upower_device(dbus->system_conn, path, state, seconds, percent); - SDL_free(path); + SDL_DBus_FreeReply(&reply); - } else if (SDL_DBus_CallMethodOnConnection(dbus->system_conn, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "EnumerateDevices", DBUS_TYPE_INVALID, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &numpaths, DBUS_TYPE_INVALID)) { + } else if (SDL_DBus_CallMethodOnConnection(dbus->system_conn, NULL, UPOWER_DBUS_NODE, UPOWER_DBUS_PATH, UPOWER_DBUS_INTERFACE, "EnumerateDevices", + DBUS_TYPE_INVALID, + DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &paths, &numpaths, DBUS_TYPE_INVALID)) { result = true; // Clearly we can use this interface. *state = SDL_POWERSTATE_NO_BATTERY; // assume we're just plugged in. *seconds = -1;