1b5975d6bSopenharmony_ciFrom 4900ea5215e329fbfe893be7975cf05ff153ef81 Mon Sep 17 00:00:00 2001 2b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 3b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:40:35 +0000 4b5975d6bSopenharmony_ciSubject: [PATCH 1/9] gdbusconnection: Fix double unref on timeout/cancel 5b5975d6bSopenharmony_ci sending a message 6b5975d6bSopenharmony_ci 7b5975d6bSopenharmony_ciThis appears to fix an intermittent failure seen when sending a D-Bus 8b5975d6bSopenharmony_cimessage with either of a cancellable or a timeout set. 9b5975d6bSopenharmony_ci 10b5975d6bSopenharmony_ciIn particular, I can reliably reproduce it with: 11b5975d6bSopenharmony_ci``` 12b5975d6bSopenharmony_cimeson test gdbus-test-codegen-min-required-2-64 --repeat 10000 13b5975d6bSopenharmony_ci``` 14b5975d6bSopenharmony_ci 15b5975d6bSopenharmony_ciIt can be caught easily with asan when reproduced. Tracking down the 16b5975d6bSopenharmony_cilocation of the refcount mismatch was a little tricky, but was 17b5975d6bSopenharmony_cisimplified by replacing a load of `g_object_ref (message)` calls with 18b5975d6bSopenharmony_ci`g_dbus_message_copy (message, NULL)` to switch `GDBusMessage` handling 19b5975d6bSopenharmony_cito using copy semantics. This allowed asan to home in on where the 20b5975d6bSopenharmony_cirefcount mismatch was happening. 21b5975d6bSopenharmony_ci 22b5975d6bSopenharmony_ciThe problem was that `send_message_data_deliver_error()` takes ownership 23b5975d6bSopenharmony_ciof the `GTask` passed to it, but the 24b5975d6bSopenharmony_ci`send_message_with_replace_cancelled_idle_cb()` and 25b5975d6bSopenharmony_ci`send_message_with_reply_timeout_cb()` functions which were calling it, 26b5975d6bSopenharmony_ciwere not passing in a strong reference as they should have. 27b5975d6bSopenharmony_ci 28b5975d6bSopenharmony_ciAnother approach to fixing this would have been to change the transfer 29b5975d6bSopenharmony_cisemantics of `send_message_data_deliver_error()` so it was `(transfer 30b5975d6bSopenharmony_cinone)` on its `GTask`. That would probably have resulted in cleaner 31b5975d6bSopenharmony_cicode, but would have been a lot harder to verify/review the fix, and 32b5975d6bSopenharmony_cieasier to inadvertently introduce new bugs. 33b5975d6bSopenharmony_ci 34b5975d6bSopenharmony_ciThe fact that the bug was only triggered by the cancellation and timeout 35b5975d6bSopenharmony_cicallbacks explains why it was intermittent: these code paths are 36b5975d6bSopenharmony_citypically never hit, but the timeout path may sometimes be hit on a very 37b5975d6bSopenharmony_cislow test run. 38b5975d6bSopenharmony_ci 39b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 40b5975d6bSopenharmony_ci 41b5975d6bSopenharmony_ciFixes: #1264 42b5975d6bSopenharmony_ci 43b5975d6bSopenharmony_ciConflict:NA 44b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/4900ea5215e329fbfe893be7975cf05ff153ef81 45b5975d6bSopenharmony_ci 46b5975d6bSopenharmony_ci--- 47b5975d6bSopenharmony_ci gio/gdbusconnection.c | 12 +++++++----- 48b5975d6bSopenharmony_ci 1 file changed, 7 insertions(+), 5 deletions(-) 49b5975d6bSopenharmony_ci 50b5975d6bSopenharmony_cidiff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c 51b5975d6bSopenharmony_ciindex d938f71b99..06c8a6141f 100644 52b5975d6bSopenharmony_ci--- a/gio/gdbusconnection.c 53b5975d6bSopenharmony_ci+++ b/gio/gdbusconnection.c 54b5975d6bSopenharmony_ci@@ -1822,7 +1822,7 @@ send_message_data_deliver_reply_unlocked (GTask *task, 55b5975d6bSopenharmony_ci ; 56b5975d6bSopenharmony_ci } 57b5975d6bSopenharmony_ci 58b5975d6bSopenharmony_ci-/* Called from a user thread, lock is not held */ 59b5975d6bSopenharmony_ci+/* Called from a user thread, lock is not held; @task is (transfer full) */ 60b5975d6bSopenharmony_ci static void 61b5975d6bSopenharmony_ci send_message_data_deliver_error (GTask *task, 62b5975d6bSopenharmony_ci GQuark domain, 63b5975d6bSopenharmony_ci@@ -1849,13 +1849,14 @@ send_message_data_deliver_error (GTask *task, 64b5975d6bSopenharmony_ci 65b5975d6bSopenharmony_ci /* ---------------------------------------------------------------------------------------------------- */ 66b5975d6bSopenharmony_ci 67b5975d6bSopenharmony_ci-/* Called from a user thread, lock is not held; @task is (transfer full) */ 68b5975d6bSopenharmony_ci+/* Called from a user thread, lock is not held; @task is (transfer none) */ 69b5975d6bSopenharmony_ci static gboolean 70b5975d6bSopenharmony_ci send_message_with_reply_cancelled_idle_cb (gpointer user_data) 71b5975d6bSopenharmony_ci { 72b5975d6bSopenharmony_ci GTask *task = user_data; 73b5975d6bSopenharmony_ci 74b5975d6bSopenharmony_ci- send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, 75b5975d6bSopenharmony_ci+ g_object_ref (task); 76b5975d6bSopenharmony_ci+ send_message_data_deliver_error (g_steal_pointer (&task), G_IO_ERROR, G_IO_ERROR_CANCELLED, 77b5975d6bSopenharmony_ci _("Operation was cancelled")); 78b5975d6bSopenharmony_ci return FALSE; 79b5975d6bSopenharmony_ci } 80b5975d6bSopenharmony_ci@@ -1879,13 +1880,14 @@ send_message_with_reply_cancelled_cb (GCancellable *cancellable, 81b5975d6bSopenharmony_ci 82b5975d6bSopenharmony_ci /* ---------------------------------------------------------------------------------------------------- */ 83b5975d6bSopenharmony_ci 84b5975d6bSopenharmony_ci-/* Called from a user thread, lock is not held; @task is (transfer full) */ 85b5975d6bSopenharmony_ci+/* Called from a user thread, lock is not held; @task is (transfer none) */ 86b5975d6bSopenharmony_ci static gboolean 87b5975d6bSopenharmony_ci send_message_with_reply_timeout_cb (gpointer user_data) 88b5975d6bSopenharmony_ci { 89b5975d6bSopenharmony_ci GTask *task = user_data; 90b5975d6bSopenharmony_ci 91b5975d6bSopenharmony_ci- send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, 92b5975d6bSopenharmony_ci+ g_object_ref (task); 93b5975d6bSopenharmony_ci+ send_message_data_deliver_error (g_steal_pointer (&task), G_IO_ERROR, G_IO_ERROR_TIMED_OUT, 94b5975d6bSopenharmony_ci _("Timeout was reached")); 95b5975d6bSopenharmony_ci return FALSE; 96b5975d6bSopenharmony_ci } 97b5975d6bSopenharmony_ci-- 98b5975d6bSopenharmony_ciGitLab 99b5975d6bSopenharmony_ci 100b5975d6bSopenharmony_ci 101b5975d6bSopenharmony_ciFrom 127c899a2e727d10eb88b8fae196add11a6c053f Mon Sep 17 00:00:00 2001 102b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 103b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:45:15 +0000 104b5975d6bSopenharmony_ciSubject: [PATCH 2/9] gdbusconnection: Fix the type of a free function 105b5975d6bSopenharmony_ciMIME-Version: 1.0 106b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 107b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 108b5975d6bSopenharmony_ci 109b5975d6bSopenharmony_ciThis didn’t actually cause any observable bugs, since the structures of 110b5975d6bSopenharmony_ci`PropertyData` and `PropertyGetAllData` were equivalent for the members 111b5975d6bSopenharmony_ciwhich the free function touches. 112b5975d6bSopenharmony_ci 113b5975d6bSopenharmony_ciDefinitely should be fixed though. 114b5975d6bSopenharmony_ci 115b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 116b5975d6bSopenharmony_ci 117b5975d6bSopenharmony_ciConflict:NA 118b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/127c899a2e727d10eb88b8fae196add11a6c053f 119b5975d6bSopenharmony_ci 120b5975d6bSopenharmony_ci--- 121b5975d6bSopenharmony_ci gio/gdbusconnection.c | 2 +- 122b5975d6bSopenharmony_ci 1 file changed, 1 insertion(+), 1 deletion(-) 123b5975d6bSopenharmony_ci 124b5975d6bSopenharmony_cidiff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c 125b5975d6bSopenharmony_ciindex 06c8a6141f..6a0d67a8ee 100644 126b5975d6bSopenharmony_ci--- a/gio/gdbusconnection.c 127b5975d6bSopenharmony_ci+++ b/gio/gdbusconnection.c 128b5975d6bSopenharmony_ci@@ -4584,7 +4584,7 @@ typedef struct 129b5975d6bSopenharmony_ci } PropertyGetAllData; 130b5975d6bSopenharmony_ci 131b5975d6bSopenharmony_ci static void 132b5975d6bSopenharmony_ci-property_get_all_data_free (PropertyData *data) 133b5975d6bSopenharmony_ci+property_get_all_data_free (PropertyGetAllData *data) 134b5975d6bSopenharmony_ci { 135b5975d6bSopenharmony_ci g_object_unref (data->connection); 136b5975d6bSopenharmony_ci g_object_unref (data->message); 137b5975d6bSopenharmony_ci-- 138b5975d6bSopenharmony_ciGitLab 139b5975d6bSopenharmony_ci 140b5975d6bSopenharmony_ci 141b5975d6bSopenharmony_ciFrom 90af20d9505a11d02e81a4f8fa09ee15faba96b8 Mon Sep 17 00:00:00 2001 142b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 143b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:46:55 +0000 144b5975d6bSopenharmony_ciSubject: [PATCH 3/9] gdbusconnection: Improve docs of message ownership in 145b5975d6bSopenharmony_ci closures 146b5975d6bSopenharmony_ci 147b5975d6bSopenharmony_ciThis introduces no functional changes, but makes it a little clearer how 148b5975d6bSopenharmony_cithe ownership of these `GDBusMessage` instances works. The free function 149b5975d6bSopenharmony_ciis changed to `g_clear_object()` to avoid the possibility of somehow 150b5975d6bSopenharmony_ciusing the messages after freeing them. 151b5975d6bSopenharmony_ci 152b5975d6bSopenharmony_ciBasically just some drive-by docs improvements while trying to debug 153b5975d6bSopenharmony_ciissue #1264. 154b5975d6bSopenharmony_ci 155b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 156b5975d6bSopenharmony_ci 157b5975d6bSopenharmony_ciHelps: #1264 158b5975d6bSopenharmony_ci 159b5975d6bSopenharmony_ciConflict:NA 160b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/90af20d9505a11d02e81a4f8fa09ee15faba96b8 161b5975d6bSopenharmony_ci 162b5975d6bSopenharmony_ci--- 163b5975d6bSopenharmony_ci gio/gdbusconnection.c | 14 +++++++------- 164b5975d6bSopenharmony_ci 1 file changed, 7 insertions(+), 7 deletions(-) 165b5975d6bSopenharmony_ci 166b5975d6bSopenharmony_cidiff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c 167b5975d6bSopenharmony_ciindex 6a0d67a8ee..0cbfc66c13 100644 168b5975d6bSopenharmony_ci--- a/gio/gdbusconnection.c 169b5975d6bSopenharmony_ci+++ b/gio/gdbusconnection.c 170b5975d6bSopenharmony_ci@@ -3743,7 +3743,7 @@ g_dbus_connection_signal_unsubscribe (GDBusConnection *connection, 171b5975d6bSopenharmony_ci typedef struct 172b5975d6bSopenharmony_ci { 173b5975d6bSopenharmony_ci SignalSubscriber *subscriber; /* (owned) */ 174b5975d6bSopenharmony_ci- GDBusMessage *message; 175b5975d6bSopenharmony_ci+ GDBusMessage *message; /* (owned) */ 176b5975d6bSopenharmony_ci GDBusConnection *connection; 177b5975d6bSopenharmony_ci const gchar *sender; /* (nullable) for peer-to-peer connections */ 178b5975d6bSopenharmony_ci const gchar *path; 179b5975d6bSopenharmony_ci@@ -3807,7 +3807,7 @@ emit_signal_instance_in_idle_cb (gpointer data) 180b5975d6bSopenharmony_ci static void 181b5975d6bSopenharmony_ci signal_instance_free (SignalInstance *signal_instance) 182b5975d6bSopenharmony_ci { 183b5975d6bSopenharmony_ci- g_object_unref (signal_instance->message); 184b5975d6bSopenharmony_ci+ g_clear_object (&signal_instance->message); 185b5975d6bSopenharmony_ci g_object_unref (signal_instance->connection); 186b5975d6bSopenharmony_ci signal_subscriber_unref (signal_instance->subscriber); 187b5975d6bSopenharmony_ci g_free (signal_instance); 188b5975d6bSopenharmony_ci@@ -4219,7 +4219,7 @@ has_object_been_unregistered (GDBusConnection *connection, 189b5975d6bSopenharmony_ci typedef struct 190b5975d6bSopenharmony_ci { 191b5975d6bSopenharmony_ci GDBusConnection *connection; 192b5975d6bSopenharmony_ci- GDBusMessage *message; 193b5975d6bSopenharmony_ci+ GDBusMessage *message; /* (owned) */ 194b5975d6bSopenharmony_ci gpointer user_data; 195b5975d6bSopenharmony_ci const gchar *property_name; 196b5975d6bSopenharmony_ci const GDBusInterfaceVTable *vtable; 197b5975d6bSopenharmony_ci@@ -4233,7 +4233,7 @@ static void 198b5975d6bSopenharmony_ci property_data_free (PropertyData *data) 199b5975d6bSopenharmony_ci { 200b5975d6bSopenharmony_ci g_object_unref (data->connection); 201b5975d6bSopenharmony_ci- g_object_unref (data->message); 202b5975d6bSopenharmony_ci+ g_clear_object (&data->message); 203b5975d6bSopenharmony_ci g_free (data); 204b5975d6bSopenharmony_ci } 205b5975d6bSopenharmony_ci 206b5975d6bSopenharmony_ci@@ -4575,7 +4575,7 @@ handle_getset_property (GDBusConnection *connection, 207b5975d6bSopenharmony_ci typedef struct 208b5975d6bSopenharmony_ci { 209b5975d6bSopenharmony_ci GDBusConnection *connection; 210b5975d6bSopenharmony_ci- GDBusMessage *message; 211b5975d6bSopenharmony_ci+ GDBusMessage *message; /* (owned) */ 212b5975d6bSopenharmony_ci gpointer user_data; 213b5975d6bSopenharmony_ci const GDBusInterfaceVTable *vtable; 214b5975d6bSopenharmony_ci GDBusInterfaceInfo *interface_info; 215b5975d6bSopenharmony_ci@@ -4587,7 +4587,7 @@ static void 216b5975d6bSopenharmony_ci property_get_all_data_free (PropertyGetAllData *data) 217b5975d6bSopenharmony_ci { 218b5975d6bSopenharmony_ci g_object_unref (data->connection); 219b5975d6bSopenharmony_ci- g_object_unref (data->message); 220b5975d6bSopenharmony_ci+ g_clear_object (&data->message); 221b5975d6bSopenharmony_ci g_free (data); 222b5975d6bSopenharmony_ci } 223b5975d6bSopenharmony_ci 224b5975d6bSopenharmony_ci@@ -6815,7 +6815,7 @@ typedef struct 225b5975d6bSopenharmony_ci static void 226b5975d6bSopenharmony_ci subtree_deferred_data_free (SubtreeDeferredData *data) 227b5975d6bSopenharmony_ci { 228b5975d6bSopenharmony_ci- g_object_unref (data->message); 229b5975d6bSopenharmony_ci+ g_clear_object (&data->message); 230b5975d6bSopenharmony_ci exported_subtree_unref (data->es); 231b5975d6bSopenharmony_ci g_free (data); 232b5975d6bSopenharmony_ci } 233b5975d6bSopenharmony_ci-- 234b5975d6bSopenharmony_ciGitLab 235b5975d6bSopenharmony_ci 236b5975d6bSopenharmony_ci 237b5975d6bSopenharmony_ciFrom ed7044b5f383cf8b77df751578e184d4ad7a134f Mon Sep 17 00:00:00 2001 238b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 239b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:49:29 +0000 240b5975d6bSopenharmony_ciSubject: [PATCH 4/9] gdbusprivate: Improve docs on message ownership in 241b5975d6bSopenharmony_ci MessageToWriteData 242b5975d6bSopenharmony_ciMIME-Version: 1.0 243b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 244b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 245b5975d6bSopenharmony_ci 246b5975d6bSopenharmony_ciThis doesn’t introduce any functional changes, but should make the code 247b5975d6bSopenharmony_cia little clearer. 248b5975d6bSopenharmony_ci 249b5975d6bSopenharmony_ciDrive-by improvements while trying to debug #1264. 250b5975d6bSopenharmony_ci 251b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 252b5975d6bSopenharmony_ci 253b5975d6bSopenharmony_ciHelps: #1264 254b5975d6bSopenharmony_ci 255b5975d6bSopenharmony_ciConflict:NA 256b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/ed7044b5f383cf8b77df751578e184d4ad7a134f 257b5975d6bSopenharmony_ci 258b5975d6bSopenharmony_ci--- 259b5975d6bSopenharmony_ci gio/gdbusprivate.c | 5 ++--- 260b5975d6bSopenharmony_ci 1 file changed, 2 insertions(+), 3 deletions(-) 261b5975d6bSopenharmony_ci 262b5975d6bSopenharmony_cidiff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c 263b5975d6bSopenharmony_ciindex 762afcee46..bd776a4214 100644 264b5975d6bSopenharmony_ci--- a/gio/gdbusprivate.c 265b5975d6bSopenharmony_ci+++ b/gio/gdbusprivate.c 266b5975d6bSopenharmony_ci@@ -889,7 +889,7 @@ _g_dbus_worker_do_initial_read (gpointer data) 267b5975d6bSopenharmony_ci struct _MessageToWriteData 268b5975d6bSopenharmony_ci { 269b5975d6bSopenharmony_ci GDBusWorker *worker; 270b5975d6bSopenharmony_ci- GDBusMessage *message; 271b5975d6bSopenharmony_ci+ GDBusMessage *message; /* (owned) */ 272b5975d6bSopenharmony_ci gchar *blob; 273b5975d6bSopenharmony_ci gsize blob_size; 274b5975d6bSopenharmony_ci 275b5975d6bSopenharmony_ci@@ -901,8 +901,7 @@ static void 276b5975d6bSopenharmony_ci message_to_write_data_free (MessageToWriteData *data) 277b5975d6bSopenharmony_ci { 278b5975d6bSopenharmony_ci _g_dbus_worker_unref (data->worker); 279b5975d6bSopenharmony_ci- if (data->message) 280b5975d6bSopenharmony_ci- g_object_unref (data->message); 281b5975d6bSopenharmony_ci+ g_clear_object (&data->message); 282b5975d6bSopenharmony_ci g_free (data->blob); 283b5975d6bSopenharmony_ci g_slice_free (MessageToWriteData, data); 284b5975d6bSopenharmony_ci } 285b5975d6bSopenharmony_ci-- 286b5975d6bSopenharmony_ciGitLab 287b5975d6bSopenharmony_ci 288b5975d6bSopenharmony_ci 289b5975d6bSopenharmony_ciFrom 861741ef4bff1a3ee15175e189136563b74fe790 Mon Sep 17 00:00:00 2001 290b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 291b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:50:47 +0000 292b5975d6bSopenharmony_ciSubject: [PATCH 5/9] gdbusprivate: Ensure data->task is cleared when it 293b5975d6bSopenharmony_ci returns 294b5975d6bSopenharmony_ciMIME-Version: 1.0 295b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 296b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 297b5975d6bSopenharmony_ci 298b5975d6bSopenharmony_ciThe existing comment in the code was correct that `data` is freed when 299b5975d6bSopenharmony_cithe task callback is called, because `data` is also pointed to by the 300b5975d6bSopenharmony_ci`user_data` for the task, and that’s freed at the end of the callback. 301b5975d6bSopenharmony_ci 302b5975d6bSopenharmony_ciSo the existing code was correct to take a copy of `data->task` before 303b5975d6bSopenharmony_cicalling `g_task_return_*()`. 304b5975d6bSopenharmony_ci 305b5975d6bSopenharmony_ciAfter calling `g_task_return_*()`, the existing code unreffed the task 306b5975d6bSopenharmony_ci(which is correct), but then didn’t clear the `data->task` pointer, 307b5975d6bSopenharmony_cileaving `data->task` dangling. That could cause a use-after-free or a 308b5975d6bSopenharmony_cidouble-unref. 309b5975d6bSopenharmony_ci 310b5975d6bSopenharmony_ciAvoid that risk by explicitly clearing `data->task` before calling 311b5975d6bSopenharmony_ci`g_task_return_*()`. 312b5975d6bSopenharmony_ci 313b5975d6bSopenharmony_ciAfter some testing, it turns out this doesn’t actually fix any bugs, but 314b5975d6bSopenharmony_ciit’s still a good robustness improvement. 315b5975d6bSopenharmony_ci 316b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 317b5975d6bSopenharmony_ci 318b5975d6bSopenharmony_ciHelps: #1264 319b5975d6bSopenharmony_ci 320b5975d6bSopenharmony_ciConflict:NA 321b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/861741ef4bff1a3ee15175e189136563b74fe790 322b5975d6bSopenharmony_ci 323b5975d6bSopenharmony_ci--- 324b5975d6bSopenharmony_ci gio/gdbusprivate.c | 54 ++++++++++++++++++++++++++++------------------ 325b5975d6bSopenharmony_ci 1 file changed, 33 insertions(+), 21 deletions(-) 326b5975d6bSopenharmony_ci 327b5975d6bSopenharmony_cidiff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c 328b5975d6bSopenharmony_ciindex bd776a4214..0b4806f524 100644 329b5975d6bSopenharmony_ci--- a/gio/gdbusprivate.c 330b5975d6bSopenharmony_ci+++ b/gio/gdbusprivate.c 331b5975d6bSopenharmony_ci@@ -894,7 +894,7 @@ struct _MessageToWriteData 332b5975d6bSopenharmony_ci gsize blob_size; 333b5975d6bSopenharmony_ci 334b5975d6bSopenharmony_ci gsize total_written; 335b5975d6bSopenharmony_ci- GTask *task; 336b5975d6bSopenharmony_ci+ GTask *task; /* (owned) and (nullable) before writing starts and after g_task_return_*() is called */ 337b5975d6bSopenharmony_ci }; 338b5975d6bSopenharmony_ci 339b5975d6bSopenharmony_ci static void 340b5975d6bSopenharmony_ci@@ -903,6 +903,11 @@ message_to_write_data_free (MessageToWriteData *data) 341b5975d6bSopenharmony_ci _g_dbus_worker_unref (data->worker); 342b5975d6bSopenharmony_ci g_clear_object (&data->message); 343b5975d6bSopenharmony_ci g_free (data->blob); 344b5975d6bSopenharmony_ci+ 345b5975d6bSopenharmony_ci+ /* The task must either not have been created, or have been created, returned 346b5975d6bSopenharmony_ci+ * and finalised by now. */ 347b5975d6bSopenharmony_ci+ g_assert (data->task == NULL); 348b5975d6bSopenharmony_ci+ 349b5975d6bSopenharmony_ci g_slice_free (MessageToWriteData, data); 350b5975d6bSopenharmony_ci } 351b5975d6bSopenharmony_ci 352b5975d6bSopenharmony_ci@@ -921,14 +926,14 @@ write_message_async_cb (GObject *source_object, 353b5975d6bSopenharmony_ci gpointer user_data) 354b5975d6bSopenharmony_ci { 355b5975d6bSopenharmony_ci MessageToWriteData *data = user_data; 356b5975d6bSopenharmony_ci- GTask *task; 357b5975d6bSopenharmony_ci gssize bytes_written; 358b5975d6bSopenharmony_ci GError *error; 359b5975d6bSopenharmony_ci 360b5975d6bSopenharmony_ci- /* Note: we can't access data->task after calling g_task_return_* () because the 361b5975d6bSopenharmony_ci- * callback can free @data and we're not completing in idle. So use a copy of the pointer. 362b5975d6bSopenharmony_ci- */ 363b5975d6bSopenharmony_ci- task = data->task; 364b5975d6bSopenharmony_ci+ /* The ownership of @data is a bit odd in this function: it’s (transfer full) 365b5975d6bSopenharmony_ci+ * when the function is called, but the code paths which call g_task_return_*() 366b5975d6bSopenharmony_ci+ * on @data->task will indirectly cause it to be freed, because @data is 367b5975d6bSopenharmony_ci+ * always guaranteed to be the user_data in the #GTask. So that’s why it looks 368b5975d6bSopenharmony_ci+ * like @data is not always freed on every code path in this function. */ 369b5975d6bSopenharmony_ci 370b5975d6bSopenharmony_ci error = NULL; 371b5975d6bSopenharmony_ci bytes_written = g_output_stream_write_finish (G_OUTPUT_STREAM (source_object), 372b5975d6bSopenharmony_ci@@ -936,8 +941,9 @@ write_message_async_cb (GObject *source_object, 373b5975d6bSopenharmony_ci &error); 374b5975d6bSopenharmony_ci if (bytes_written == -1) 375b5975d6bSopenharmony_ci { 376b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 377b5975d6bSopenharmony_ci g_task_return_error (task, error); 378b5975d6bSopenharmony_ci- g_object_unref (task); 379b5975d6bSopenharmony_ci+ g_clear_object (&task); 380b5975d6bSopenharmony_ci goto out; 381b5975d6bSopenharmony_ci } 382b5975d6bSopenharmony_ci g_assert (bytes_written > 0); /* zero is never returned */ 383b5975d6bSopenharmony_ci@@ -948,8 +954,9 @@ write_message_async_cb (GObject *source_object, 384b5975d6bSopenharmony_ci g_assert (data->total_written <= data->blob_size); 385b5975d6bSopenharmony_ci if (data->total_written == data->blob_size) 386b5975d6bSopenharmony_ci { 387b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 388b5975d6bSopenharmony_ci g_task_return_boolean (task, TRUE); 389b5975d6bSopenharmony_ci- g_object_unref (task); 390b5975d6bSopenharmony_ci+ g_clear_object (&task); 391b5975d6bSopenharmony_ci goto out; 392b5975d6bSopenharmony_ci } 393b5975d6bSopenharmony_ci 394b5975d6bSopenharmony_ci@@ -986,16 +993,14 @@ write_message_continue_writing (MessageToWriteData *data) 395b5975d6bSopenharmony_ci { 396b5975d6bSopenharmony_ci GOutputStream *ostream; 397b5975d6bSopenharmony_ci #ifdef G_OS_UNIX 398b5975d6bSopenharmony_ci- GTask *task; 399b5975d6bSopenharmony_ci GUnixFDList *fd_list; 400b5975d6bSopenharmony_ci #endif 401b5975d6bSopenharmony_ci 402b5975d6bSopenharmony_ci-#ifdef G_OS_UNIX 403b5975d6bSopenharmony_ci- /* Note: we can't access data->task after calling g_task_return_* () because the 404b5975d6bSopenharmony_ci- * callback can free @data and we're not completing in idle. So use a copy of the pointer. 405b5975d6bSopenharmony_ci- */ 406b5975d6bSopenharmony_ci- task = data->task; 407b5975d6bSopenharmony_ci-#endif 408b5975d6bSopenharmony_ci+ /* The ownership of @data is a bit odd in this function: it’s (transfer full) 409b5975d6bSopenharmony_ci+ * when the function is called, but the code paths which call g_task_return_*() 410b5975d6bSopenharmony_ci+ * on @data->task will indirectly cause it to be freed, because @data is 411b5975d6bSopenharmony_ci+ * always guaranteed to be the user_data in the #GTask. So that’s why it looks 412b5975d6bSopenharmony_ci+ * like @data is not always freed on every code path in this function. */ 413b5975d6bSopenharmony_ci 414b5975d6bSopenharmony_ci ostream = g_io_stream_get_output_stream (data->worker->stream); 415b5975d6bSopenharmony_ci #ifdef G_OS_UNIX 416b5975d6bSopenharmony_ci@@ -1024,11 +1029,12 @@ write_message_continue_writing (MessageToWriteData *data) 417b5975d6bSopenharmony_ci { 418b5975d6bSopenharmony_ci if (!(data->worker->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING)) 419b5975d6bSopenharmony_ci { 420b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 421b5975d6bSopenharmony_ci g_task_return_new_error (task, 422b5975d6bSopenharmony_ci G_IO_ERROR, 423b5975d6bSopenharmony_ci G_IO_ERROR_FAILED, 424b5975d6bSopenharmony_ci "Tried sending a file descriptor but remote peer does not support this capability"); 425b5975d6bSopenharmony_ci- g_object_unref (task); 426b5975d6bSopenharmony_ci+ g_clear_object (&task); 427b5975d6bSopenharmony_ci goto out; 428b5975d6bSopenharmony_ci } 429b5975d6bSopenharmony_ci control_message = g_unix_fd_message_new_with_fd_list (fd_list); 430b5975d6bSopenharmony_ci@@ -1065,9 +1071,13 @@ write_message_continue_writing (MessageToWriteData *data) 431b5975d6bSopenharmony_ci g_error_free (error); 432b5975d6bSopenharmony_ci goto out; 433b5975d6bSopenharmony_ci } 434b5975d6bSopenharmony_ci- g_task_return_error (task, error); 435b5975d6bSopenharmony_ci- g_object_unref (task); 436b5975d6bSopenharmony_ci- goto out; 437b5975d6bSopenharmony_ci+ else 438b5975d6bSopenharmony_ci+ { 439b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 440b5975d6bSopenharmony_ci+ g_task_return_error (task, error); 441b5975d6bSopenharmony_ci+ g_clear_object (&task); 442b5975d6bSopenharmony_ci+ goto out; 443b5975d6bSopenharmony_ci+ } 444b5975d6bSopenharmony_ci } 445b5975d6bSopenharmony_ci g_assert (bytes_written > 0); /* zero is never returned */ 446b5975d6bSopenharmony_ci 447b5975d6bSopenharmony_ci@@ -1077,8 +1087,9 @@ write_message_continue_writing (MessageToWriteData *data) 448b5975d6bSopenharmony_ci g_assert (data->total_written <= data->blob_size); 449b5975d6bSopenharmony_ci if (data->total_written == data->blob_size) 450b5975d6bSopenharmony_ci { 451b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 452b5975d6bSopenharmony_ci g_task_return_boolean (task, TRUE); 453b5975d6bSopenharmony_ci- g_object_unref (task); 454b5975d6bSopenharmony_ci+ g_clear_object (&task); 455b5975d6bSopenharmony_ci goto out; 456b5975d6bSopenharmony_ci } 457b5975d6bSopenharmony_ci 458b5975d6bSopenharmony_ci@@ -1093,12 +1104,13 @@ write_message_continue_writing (MessageToWriteData *data) 459b5975d6bSopenharmony_ci /* We were trying to write byte 0 of the message, which needs 460b5975d6bSopenharmony_ci * the fd list to be attached to it, but this connection doesn't 461b5975d6bSopenharmony_ci * support doing that. */ 462b5975d6bSopenharmony_ci+ GTask *task = g_steal_pointer (&data->task); 463b5975d6bSopenharmony_ci g_task_return_new_error (task, 464b5975d6bSopenharmony_ci G_IO_ERROR, 465b5975d6bSopenharmony_ci G_IO_ERROR_FAILED, 466b5975d6bSopenharmony_ci "Tried sending a file descriptor on unsupported stream of type %s", 467b5975d6bSopenharmony_ci g_type_name (G_TYPE_FROM_INSTANCE (ostream))); 468b5975d6bSopenharmony_ci- g_object_unref (task); 469b5975d6bSopenharmony_ci+ g_clear_object (&task); 470b5975d6bSopenharmony_ci goto out; 471b5975d6bSopenharmony_ci } 472b5975d6bSopenharmony_ci #endif 473b5975d6bSopenharmony_ci-- 474b5975d6bSopenharmony_ciGitLab 475b5975d6bSopenharmony_ci 476b5975d6bSopenharmony_ci 477b5975d6bSopenharmony_ciFrom d7c813cf5b6148c18184e4f1af23d234e73aafb8 Mon Sep 17 00:00:00 2001 478b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 479b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:56:56 +0000 480b5975d6bSopenharmony_ciSubject: [PATCH 6/9] gdbusprivate: Improve ownership docs for 481b5975d6bSopenharmony_ci write_message_async() 482b5975d6bSopenharmony_ciMIME-Version: 1.0 483b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 484b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 485b5975d6bSopenharmony_ci 486b5975d6bSopenharmony_ciThe ownership transfers in this code are a bit complex, so adding some 487b5975d6bSopenharmony_ciextra documentation and `g_steal_pointer()` calls should hopefully help 488b5975d6bSopenharmony_ciclarify things. 489b5975d6bSopenharmony_ci 490b5975d6bSopenharmony_ciThis doesn’t introduce any functional changes, just code documentation. 491b5975d6bSopenharmony_ci 492b5975d6bSopenharmony_ciAnother drive-by improvement in the quest for #1264. 493b5975d6bSopenharmony_ci 494b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 495b5975d6bSopenharmony_ci 496b5975d6bSopenharmony_ciHelps: #1264 497b5975d6bSopenharmony_ci 498b5975d6bSopenharmony_ciConflict:NA 499b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/d7c813cf5b6148c18184e4f1af23d234e73aafb8 500b5975d6bSopenharmony_ci 501b5975d6bSopenharmony_ci--- 502b5975d6bSopenharmony_ci gio/gdbusprivate.c | 21 ++++++++++++--------- 503b5975d6bSopenharmony_ci 1 file changed, 12 insertions(+), 9 deletions(-) 504b5975d6bSopenharmony_ci 505b5975d6bSopenharmony_cidiff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c 506b5975d6bSopenharmony_ciindex 0b4806f524..5aa141a60e 100644 507b5975d6bSopenharmony_ci--- a/gio/gdbusprivate.c 508b5975d6bSopenharmony_ci+++ b/gio/gdbusprivate.c 509b5975d6bSopenharmony_ci@@ -919,13 +919,14 @@ static void write_message_continue_writing (MessageToWriteData *data); 510b5975d6bSopenharmony_ci * 511b5975d6bSopenharmony_ci * write-lock is not held on entry 512b5975d6bSopenharmony_ci * output_pending is PENDING_WRITE on entry 513b5975d6bSopenharmony_ci+ * @user_data is (transfer full) 514b5975d6bSopenharmony_ci */ 515b5975d6bSopenharmony_ci static void 516b5975d6bSopenharmony_ci write_message_async_cb (GObject *source_object, 517b5975d6bSopenharmony_ci GAsyncResult *res, 518b5975d6bSopenharmony_ci gpointer user_data) 519b5975d6bSopenharmony_ci { 520b5975d6bSopenharmony_ci- MessageToWriteData *data = user_data; 521b5975d6bSopenharmony_ci+ MessageToWriteData *data = g_steal_pointer (&user_data); 522b5975d6bSopenharmony_ci gssize bytes_written; 523b5975d6bSopenharmony_ci GError *error; 524b5975d6bSopenharmony_ci 525b5975d6bSopenharmony_ci@@ -960,7 +961,7 @@ write_message_async_cb (GObject *source_object, 526b5975d6bSopenharmony_ci goto out; 527b5975d6bSopenharmony_ci } 528b5975d6bSopenharmony_ci 529b5975d6bSopenharmony_ci- write_message_continue_writing (data); 530b5975d6bSopenharmony_ci+ write_message_continue_writing (g_steal_pointer (&data)); 531b5975d6bSopenharmony_ci 532b5975d6bSopenharmony_ci out: 533b5975d6bSopenharmony_ci ; 534b5975d6bSopenharmony_ci@@ -977,8 +978,8 @@ on_socket_ready (GSocket *socket, 535b5975d6bSopenharmony_ci GIOCondition condition, 536b5975d6bSopenharmony_ci gpointer user_data) 537b5975d6bSopenharmony_ci { 538b5975d6bSopenharmony_ci- MessageToWriteData *data = user_data; 539b5975d6bSopenharmony_ci- write_message_continue_writing (data); 540b5975d6bSopenharmony_ci+ MessageToWriteData *data = g_steal_pointer (&user_data); 541b5975d6bSopenharmony_ci+ write_message_continue_writing (g_steal_pointer (&data)); 542b5975d6bSopenharmony_ci return FALSE; /* remove source */ 543b5975d6bSopenharmony_ci } 544b5975d6bSopenharmony_ci #endif 545b5975d6bSopenharmony_ci@@ -987,6 +988,7 @@ on_socket_ready (GSocket *socket, 546b5975d6bSopenharmony_ci * 547b5975d6bSopenharmony_ci * write-lock is not held on entry 548b5975d6bSopenharmony_ci * output_pending is PENDING_WRITE on entry 549b5975d6bSopenharmony_ci+ * @data is (transfer full) 550b5975d6bSopenharmony_ci */ 551b5975d6bSopenharmony_ci static void 552b5975d6bSopenharmony_ci write_message_continue_writing (MessageToWriteData *data) 553b5975d6bSopenharmony_ci@@ -1064,7 +1066,7 @@ write_message_continue_writing (MessageToWriteData *data) 554b5975d6bSopenharmony_ci data->worker->cancellable); 555b5975d6bSopenharmony_ci g_source_set_callback (source, 556b5975d6bSopenharmony_ci (GSourceFunc) on_socket_ready, 557b5975d6bSopenharmony_ci- data, 558b5975d6bSopenharmony_ci+ g_steal_pointer (&data), 559b5975d6bSopenharmony_ci NULL); /* GDestroyNotify */ 560b5975d6bSopenharmony_ci g_source_attach (source, g_main_context_get_thread_default ()); 561b5975d6bSopenharmony_ci g_source_unref (source); 562b5975d6bSopenharmony_ci@@ -1093,7 +1095,7 @@ write_message_continue_writing (MessageToWriteData *data) 563b5975d6bSopenharmony_ci goto out; 564b5975d6bSopenharmony_ci } 565b5975d6bSopenharmony_ci 566b5975d6bSopenharmony_ci- write_message_continue_writing (data); 567b5975d6bSopenharmony_ci+ write_message_continue_writing (g_steal_pointer (&data)); 568b5975d6bSopenharmony_ci } 569b5975d6bSopenharmony_ci #endif 570b5975d6bSopenharmony_ci else 571b5975d6bSopenharmony_ci@@ -1121,7 +1123,7 @@ write_message_continue_writing (MessageToWriteData *data) 572b5975d6bSopenharmony_ci G_PRIORITY_DEFAULT, 573b5975d6bSopenharmony_ci data->worker->cancellable, 574b5975d6bSopenharmony_ci write_message_async_cb, 575b5975d6bSopenharmony_ci- data); 576b5975d6bSopenharmony_ci+ data); /* steal @data */ 577b5975d6bSopenharmony_ci } 578b5975d6bSopenharmony_ci #ifdef G_OS_UNIX 579b5975d6bSopenharmony_ci out: 580b5975d6bSopenharmony_ci@@ -1144,7 +1146,7 @@ write_message_async (GDBusWorker *worker, 581b5975d6bSopenharmony_ci g_task_set_source_tag (data->task, write_message_async); 582b5975d6bSopenharmony_ci g_task_set_name (data->task, "[gio] D-Bus write message"); 583b5975d6bSopenharmony_ci data->total_written = 0; 584b5975d6bSopenharmony_ci- write_message_continue_writing (data); 585b5975d6bSopenharmony_ci+ write_message_continue_writing (g_steal_pointer (&data)); 586b5975d6bSopenharmony_ci } 587b5975d6bSopenharmony_ci 588b5975d6bSopenharmony_ci /* called in private thread shared by all GDBusConnection instances (with write-lock held) */ 589b5975d6bSopenharmony_ci@@ -1333,6 +1335,7 @@ prepare_flush_unlocked (GDBusWorker *worker) 590b5975d6bSopenharmony_ci * 591b5975d6bSopenharmony_ci * write-lock is not held on entry 592b5975d6bSopenharmony_ci * output_pending is PENDING_WRITE on entry 593b5975d6bSopenharmony_ci+ * @user_data is (transfer full) 594b5975d6bSopenharmony_ci */ 595b5975d6bSopenharmony_ci static void 596b5975d6bSopenharmony_ci write_message_cb (GObject *source_object, 597b5975d6bSopenharmony_ci@@ -1551,7 +1554,7 @@ continue_writing (GDBusWorker *worker) 598b5975d6bSopenharmony_ci write_message_async (worker, 599b5975d6bSopenharmony_ci data, 600b5975d6bSopenharmony_ci write_message_cb, 601b5975d6bSopenharmony_ci- data); 602b5975d6bSopenharmony_ci+ data); /* takes ownership of @data as user_data */ 603b5975d6bSopenharmony_ci } 604b5975d6bSopenharmony_ci } 605b5975d6bSopenharmony_ci 606b5975d6bSopenharmony_ci-- 607b5975d6bSopenharmony_ciGitLab 608b5975d6bSopenharmony_ci 609b5975d6bSopenharmony_ci 610b5975d6bSopenharmony_ciFrom 08a4387678346caaa42b69e5e6e5995d48cd61c4 Mon Sep 17 00:00:00 2001 611b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 612b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 02:58:05 +0000 613b5975d6bSopenharmony_ciSubject: [PATCH 7/9] gdbusprivate: Use G_SOURCE_REMOVE in a source callback 614b5975d6bSopenharmony_ci 615b5975d6bSopenharmony_ciThis is equivalent to the current behaviour, but a little clearer in its 616b5975d6bSopenharmony_cimeaning. 617b5975d6bSopenharmony_ci 618b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 619b5975d6bSopenharmony_ci 620b5975d6bSopenharmony_ciHelps: #1264 621b5975d6bSopenharmony_ci 622b5975d6bSopenharmony_ciConflict:NA 623b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/08a4387678346caaa42b69e5e6e5995d48cd61c4 624b5975d6bSopenharmony_ci 625b5975d6bSopenharmony_ci--- 626b5975d6bSopenharmony_ci gio/gdbusprivate.c | 2 +- 627b5975d6bSopenharmony_ci 1 file changed, 1 insertion(+), 1 deletion(-) 628b5975d6bSopenharmony_ci 629b5975d6bSopenharmony_cidiff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c 630b5975d6bSopenharmony_ciindex 5aa141a60e..2c9238c638 100644 631b5975d6bSopenharmony_ci--- a/gio/gdbusprivate.c 632b5975d6bSopenharmony_ci+++ b/gio/gdbusprivate.c 633b5975d6bSopenharmony_ci@@ -980,7 +980,7 @@ on_socket_ready (GSocket *socket, 634b5975d6bSopenharmony_ci { 635b5975d6bSopenharmony_ci MessageToWriteData *data = g_steal_pointer (&user_data); 636b5975d6bSopenharmony_ci write_message_continue_writing (g_steal_pointer (&data)); 637b5975d6bSopenharmony_ci- return FALSE; /* remove source */ 638b5975d6bSopenharmony_ci+ return G_SOURCE_REMOVE; 639b5975d6bSopenharmony_ci } 640b5975d6bSopenharmony_ci #endif 641b5975d6bSopenharmony_ci 642b5975d6bSopenharmony_ci-- 643b5975d6bSopenharmony_ciGitLab 644b5975d6bSopenharmony_ci 645b5975d6bSopenharmony_ci 646b5975d6bSopenharmony_ciFrom b84ec21f9c4c57990309e691206582c589f59770 Mon Sep 17 00:00:00 2001 647b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 648b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 12:19:16 +0000 649b5975d6bSopenharmony_ciSubject: [PATCH 8/9] gdbusconnection: Rearrange refcount handling of 650b5975d6bSopenharmony_ci map_method_serial_to_task 651b5975d6bSopenharmony_ciMIME-Version: 1.0 652b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 653b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 654b5975d6bSopenharmony_ci 655b5975d6bSopenharmony_ciIt already implicitly held a strong ref on its `GTask` values, but 656b5975d6bSopenharmony_cididn’t have a free function set so that they would be automatically 657b5975d6bSopenharmony_ciunreffed on removal from the map. 658b5975d6bSopenharmony_ci 659b5975d6bSopenharmony_ciThis meant that the functions handling removals from the map, 660b5975d6bSopenharmony_ci`on_worker_closed()` (via `cancel_method_on_close()`) and 661b5975d6bSopenharmony_ci`send_message_with_reply_cleanup()` had to call unref once more than 662b5975d6bSopenharmony_cithey would otherwise. 663b5975d6bSopenharmony_ci 664b5975d6bSopenharmony_ciIn `send_message_with_reply_cleanup()`, this behaviour depended on 665b5975d6bSopenharmony_ciwhether it was called with `remove == TRUE`. If not, it was `(transfer 666b5975d6bSopenharmony_cinone)` not `(transfer full)`. This led to bugs in its callers. 667b5975d6bSopenharmony_ci 668b5975d6bSopenharmony_ciFor example, this led to a direct leak in `cancel_method_on_close()`, as 669b5975d6bSopenharmony_ciit needed to remove tasks from `map_method_serial_to_task`, but called 670b5975d6bSopenharmony_ci`send_message_with_reply_cleanup(remove = FALSE)` and erroneously didn’t 671b5975d6bSopenharmony_cicall unref an additional time. 672b5975d6bSopenharmony_ci 673b5975d6bSopenharmony_ciTry and simplify it all by setting a `GDestroyNotify` on 674b5975d6bSopenharmony_ci`map_method_serial_to_task`’s values, and making the refcount handling 675b5975d6bSopenharmony_ciof `send_message_with_reply_cleanup()` not be conditional on its 676b5975d6bSopenharmony_ciarguments. 677b5975d6bSopenharmony_ci 678b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 679b5975d6bSopenharmony_ci 680b5975d6bSopenharmony_ciHelps: #1264 681b5975d6bSopenharmony_ci 682b5975d6bSopenharmony_ciConflict:NA 683b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/b84ec21f9c4c57990309e691206582c589f59770 684b5975d6bSopenharmony_ci 685b5975d6bSopenharmony_ci--- 686b5975d6bSopenharmony_ci gio/gdbusconnection.c | 24 ++++++++++++------------ 687b5975d6bSopenharmony_ci 1 file changed, 12 insertions(+), 12 deletions(-) 688b5975d6bSopenharmony_ci 689b5975d6bSopenharmony_cidiff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c 690b5975d6bSopenharmony_ciindex 0cbfc66c13..f4bc21bb37 100644 691b5975d6bSopenharmony_ci--- a/gio/gdbusconnection.c 692b5975d6bSopenharmony_ci+++ b/gio/gdbusconnection.c 693b5975d6bSopenharmony_ci@@ -409,7 +409,7 @@ struct _GDBusConnection 694b5975d6bSopenharmony_ci GDBusConnectionFlags flags; 695b5975d6bSopenharmony_ci 696b5975d6bSopenharmony_ci /* Map used for managing method replies, protected by @lock */ 697b5975d6bSopenharmony_ci- GHashTable *map_method_serial_to_task; /* guint32 -> GTask* */ 698b5975d6bSopenharmony_ci+ GHashTable *map_method_serial_to_task; /* guint32 -> owned GTask* */ 699b5975d6bSopenharmony_ci 700b5975d6bSopenharmony_ci /* Maps used for managing signal subscription, protected by @lock */ 701b5975d6bSopenharmony_ci GHashTable *map_rule_to_signal_data; /* match rule (gchar*) -> SignalData */ 702b5975d6bSopenharmony_ci@@ -1061,7 +1061,7 @@ g_dbus_connection_init (GDBusConnection *connection) 703b5975d6bSopenharmony_ci g_mutex_init (&connection->lock); 704b5975d6bSopenharmony_ci g_mutex_init (&connection->init_lock); 705b5975d6bSopenharmony_ci 706b5975d6bSopenharmony_ci- connection->map_method_serial_to_task = g_hash_table_new (g_direct_hash, g_direct_equal); 707b5975d6bSopenharmony_ci+ connection->map_method_serial_to_task = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); 708b5975d6bSopenharmony_ci 709b5975d6bSopenharmony_ci connection->map_rule_to_signal_data = g_hash_table_new (g_str_hash, 710b5975d6bSopenharmony_ci g_str_equal); 711b5975d6bSopenharmony_ci@@ -1768,7 +1768,7 @@ send_message_data_free (SendMessageData *data) 712b5975d6bSopenharmony_ci 713b5975d6bSopenharmony_ci /* ---------------------------------------------------------------------------------------------------- */ 714b5975d6bSopenharmony_ci 715b5975d6bSopenharmony_ci-/* can be called from any thread with lock held; @task is (transfer full) */ 716b5975d6bSopenharmony_ci+/* can be called from any thread with lock held; @task is (transfer none) */ 717b5975d6bSopenharmony_ci static void 718b5975d6bSopenharmony_ci send_message_with_reply_cleanup (GTask *task, gboolean remove) 719b5975d6bSopenharmony_ci { 720b5975d6bSopenharmony_ci@@ -1798,13 +1798,11 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove) 721b5975d6bSopenharmony_ci GUINT_TO_POINTER (data->serial)); 722b5975d6bSopenharmony_ci g_warn_if_fail (removed); 723b5975d6bSopenharmony_ci } 724b5975d6bSopenharmony_ci- 725b5975d6bSopenharmony_ci- g_object_unref (task); 726b5975d6bSopenharmony_ci } 727b5975d6bSopenharmony_ci 728b5975d6bSopenharmony_ci /* ---------------------------------------------------------------------------------------------------- */ 729b5975d6bSopenharmony_ci 730b5975d6bSopenharmony_ci-/* Called from GDBus worker thread with lock held; @task is (transfer full). */ 731b5975d6bSopenharmony_ci+/* Called from GDBus worker thread with lock held; @task is (transfer none). */ 732b5975d6bSopenharmony_ci static void 733b5975d6bSopenharmony_ci send_message_data_deliver_reply_unlocked (GTask *task, 734b5975d6bSopenharmony_ci GDBusMessage *reply) 735b5975d6bSopenharmony_ci@@ -1822,7 +1820,7 @@ send_message_data_deliver_reply_unlocked (GTask *task, 736b5975d6bSopenharmony_ci ; 737b5975d6bSopenharmony_ci } 738b5975d6bSopenharmony_ci 739b5975d6bSopenharmony_ci-/* Called from a user thread, lock is not held; @task is (transfer full) */ 740b5975d6bSopenharmony_ci+/* Called from a user thread, lock is not held; @task is (transfer none) */ 741b5975d6bSopenharmony_ci static void 742b5975d6bSopenharmony_ci send_message_data_deliver_error (GTask *task, 743b5975d6bSopenharmony_ci GQuark domain, 744b5975d6bSopenharmony_ci@@ -1839,7 +1837,10 @@ send_message_data_deliver_error (GTask *task, 745b5975d6bSopenharmony_ci return; 746b5975d6bSopenharmony_ci } 747b5975d6bSopenharmony_ci 748b5975d6bSopenharmony_ci+ /* Hold a ref on @task as send_message_with_reply_cleanup() will remove it 749b5975d6bSopenharmony_ci+ * from the task map and could end up dropping the last reference */ 750b5975d6bSopenharmony_ci g_object_ref (task); 751b5975d6bSopenharmony_ci+ 752b5975d6bSopenharmony_ci send_message_with_reply_cleanup (task, TRUE); 753b5975d6bSopenharmony_ci CONNECTION_UNLOCK (connection); 754b5975d6bSopenharmony_ci 755b5975d6bSopenharmony_ci@@ -1855,8 +1856,7 @@ send_message_with_reply_cancelled_idle_cb (gpointer user_data) 756b5975d6bSopenharmony_ci { 757b5975d6bSopenharmony_ci GTask *task = user_data; 758b5975d6bSopenharmony_ci 759b5975d6bSopenharmony_ci- g_object_ref (task); 760b5975d6bSopenharmony_ci- send_message_data_deliver_error (g_steal_pointer (&task), G_IO_ERROR, G_IO_ERROR_CANCELLED, 761b5975d6bSopenharmony_ci+ send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, 762b5975d6bSopenharmony_ci _("Operation was cancelled")); 763b5975d6bSopenharmony_ci return FALSE; 764b5975d6bSopenharmony_ci } 765b5975d6bSopenharmony_ci@@ -1886,8 +1886,7 @@ send_message_with_reply_timeout_cb (gpointer user_data) 766b5975d6bSopenharmony_ci { 767b5975d6bSopenharmony_ci GTask *task = user_data; 768b5975d6bSopenharmony_ci 769b5975d6bSopenharmony_ci- g_object_ref (task); 770b5975d6bSopenharmony_ci- send_message_data_deliver_error (g_steal_pointer (&task), G_IO_ERROR, G_IO_ERROR_TIMED_OUT, 771b5975d6bSopenharmony_ci+ send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, 772b5975d6bSopenharmony_ci _("Timeout was reached")); 773b5975d6bSopenharmony_ci return FALSE; 774b5975d6bSopenharmony_ci } 775b5975d6bSopenharmony_ci@@ -2391,7 +2390,8 @@ on_worker_message_about_to_be_sent (GDBusWorker *worker, 776b5975d6bSopenharmony_ci return message; 777b5975d6bSopenharmony_ci } 778b5975d6bSopenharmony_ci 779b5975d6bSopenharmony_ci-/* called with connection lock held, in GDBusWorker thread */ 780b5975d6bSopenharmony_ci+/* called with connection lock held, in GDBusWorker thread 781b5975d6bSopenharmony_ci+ * @key, @value and @user_data are (transfer none) */ 782b5975d6bSopenharmony_ci static gboolean 783b5975d6bSopenharmony_ci cancel_method_on_close (gpointer key, gpointer value, gpointer user_data) 784b5975d6bSopenharmony_ci { 785b5975d6bSopenharmony_ci-- 786b5975d6bSopenharmony_ciGitLab 787b5975d6bSopenharmony_ci 788b5975d6bSopenharmony_ci 789b5975d6bSopenharmony_ciFrom 0a84c182e28f50be2263e42e0bc21074dd523701 Mon Sep 17 00:00:00 2001 790b5975d6bSopenharmony_ciFrom: Philip Withnall <pwithnall@endlessos.org> 791b5975d6bSopenharmony_ciDate: Wed, 22 Feb 2023 14:55:40 +0000 792b5975d6bSopenharmony_ciSubject: [PATCH 9/9] gdbusconnection: Improve refcount handling of timeout 793b5975d6bSopenharmony_ci source 794b5975d6bSopenharmony_ciMIME-Version: 1.0 795b5975d6bSopenharmony_ciContent-Type: text/plain; charset=UTF-8 796b5975d6bSopenharmony_ciContent-Transfer-Encoding: 8bit 797b5975d6bSopenharmony_ci 798b5975d6bSopenharmony_ciThe ref on the timeout source owned by `SendMessageData` was being 799b5975d6bSopenharmony_cidropped just after attaching the source to the main context, leaving it 800b5975d6bSopenharmony_ciunowned in that struct. That meant the only ref on the source was held 801b5975d6bSopenharmony_ciby the `GMainContext` it was attached to. 802b5975d6bSopenharmony_ci 803b5975d6bSopenharmony_ciThis ref was dropped when returning `G_SOURCE_REMOVE` from 804b5975d6bSopenharmony_ci`send_message_with_reply_timeout_cb()`. Before that happens, 805b5975d6bSopenharmony_ci`send_message_data_deliver_error()` is called, which normally calls 806b5975d6bSopenharmony_ci`send_message_with_reply_cleanup()` and destroys the source. 807b5975d6bSopenharmony_ci 808b5975d6bSopenharmony_ciHowever, if `send_message_data_deliver_error()` is called when the 809b5975d6bSopenharmony_cimessage has already been delivered, calling 810b5975d6bSopenharmony_ci`send_message_with_reply_cleanup()` will be skipped. This leaves the 811b5975d6bSopenharmony_cisource pointer in `SendMessageData` dangling, which will cause problems 812b5975d6bSopenharmony_ciwhen `g_source_destroy()` is subsequently called on it. 813b5975d6bSopenharmony_ci 814b5975d6bSopenharmony_ciI’m not sure if it’s possible in practice for this situation to occur, 815b5975d6bSopenharmony_cibut the code certainly does nothing to prevent it, and it’s easy enough 816b5975d6bSopenharmony_cito avoid by keeping a strong ref on the source in `SendMessageData`. 817b5975d6bSopenharmony_ci 818b5975d6bSopenharmony_ciSigned-off-by: Philip Withnall <pwithnall@endlessos.org> 819b5975d6bSopenharmony_ci 820b5975d6bSopenharmony_ciHelps: #1264 821b5975d6bSopenharmony_ci 822b5975d6bSopenharmony_ciConflict:NA 823b5975d6bSopenharmony_ciReference:https://gitlab.gnome.org/GNOME/glib/-/commit/0a84c182e28f50be2263e42e0bc21074dd523701 824b5975d6bSopenharmony_ci 825b5975d6bSopenharmony_ci--- 826b5975d6bSopenharmony_ci gio/gdbusconnection.c | 8 ++++---- 827b5975d6bSopenharmony_ci 1 file changed, 4 insertions(+), 4 deletions(-) 828b5975d6bSopenharmony_ci 829b5975d6bSopenharmony_cidiff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c 830b5975d6bSopenharmony_ciindex f4bc21bb37..bed1ff2841 100644 831b5975d6bSopenharmony_ci--- a/gio/gdbusconnection.c 832b5975d6bSopenharmony_ci+++ b/gio/gdbusconnection.c 833b5975d6bSopenharmony_ci@@ -1751,7 +1751,7 @@ typedef struct 834b5975d6bSopenharmony_ci 835b5975d6bSopenharmony_ci gulong cancellable_handler_id; 836b5975d6bSopenharmony_ci 837b5975d6bSopenharmony_ci- GSource *timeout_source; 838b5975d6bSopenharmony_ci+ GSource *timeout_source; /* (owned) (nullable) */ 839b5975d6bSopenharmony_ci 840b5975d6bSopenharmony_ci gboolean delivered; 841b5975d6bSopenharmony_ci } SendMessageData; 842b5975d6bSopenharmony_ci@@ -1760,6 +1760,7 @@ typedef struct 843b5975d6bSopenharmony_ci static void 844b5975d6bSopenharmony_ci send_message_data_free (SendMessageData *data) 845b5975d6bSopenharmony_ci { 846b5975d6bSopenharmony_ci+ /* These should already have been cleared by send_message_with_reply_cleanup(). */ 847b5975d6bSopenharmony_ci g_assert (data->timeout_source == NULL); 848b5975d6bSopenharmony_ci g_assert (data->cancellable_handler_id == 0); 849b5975d6bSopenharmony_ci 850b5975d6bSopenharmony_ci@@ -1784,7 +1785,7 @@ send_message_with_reply_cleanup (GTask *task, gboolean remove) 851b5975d6bSopenharmony_ci if (data->timeout_source != NULL) 852b5975d6bSopenharmony_ci { 853b5975d6bSopenharmony_ci g_source_destroy (data->timeout_source); 854b5975d6bSopenharmony_ci- data->timeout_source = NULL; 855b5975d6bSopenharmony_ci+ g_clear_pointer (&data->timeout_source, g_source_unref); 856b5975d6bSopenharmony_ci } 857b5975d6bSopenharmony_ci if (data->cancellable_handler_id > 0) 858b5975d6bSopenharmony_ci { 859b5975d6bSopenharmony_ci@@ -1888,7 +1889,7 @@ send_message_with_reply_timeout_cb (gpointer user_data) 860b5975d6bSopenharmony_ci 861b5975d6bSopenharmony_ci send_message_data_deliver_error (task, G_IO_ERROR, G_IO_ERROR_TIMED_OUT, 862b5975d6bSopenharmony_ci _("Timeout was reached")); 863b5975d6bSopenharmony_ci- return FALSE; 864b5975d6bSopenharmony_ci+ return G_SOURCE_REMOVE; 865b5975d6bSopenharmony_ci } 866b5975d6bSopenharmony_ci 867b5975d6bSopenharmony_ci /* ---------------------------------------------------------------------------------------------------- */ 868b5975d6bSopenharmony_ci@@ -1949,7 +1950,6 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection *connect 869b5975d6bSopenharmony_ci data->timeout_source = g_timeout_source_new (timeout_msec); 870b5975d6bSopenharmony_ci g_task_attach_source (task, data->timeout_source, 871b5975d6bSopenharmony_ci (GSourceFunc) send_message_with_reply_timeout_cb); 872b5975d6bSopenharmony_ci- g_source_unref (data->timeout_source); 873b5975d6bSopenharmony_ci } 874b5975d6bSopenharmony_ci 875b5975d6bSopenharmony_ci g_hash_table_insert (connection->map_method_serial_to_task, 876b5975d6bSopenharmony_ci-- 877b5975d6bSopenharmony_ciGitLab