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