[glib/glib-2-72: 1/2] gsocketclient: Fix passing NULL to g_task_get_cancellable()




commit 99783e0408f8ae9628d2c7a30eb99806087da711
Author: Philip Withnall <pwithnall endlessos org>
Date:   Tue Jul 12 16:07:23 2022 +0100

    gsocketclient: Fix passing NULL to g_task_get_cancellable()
    
    Fix a regression from commit abddb42d14, where it could pass `NULL` to
    `g_task_get_cancellable()`, triggering a critical warning. This could
    happen because the lifetime of `data->task` is not as long as the
    lifetime of the `ConnectionAttempt`, but the code assumed it was.
    
    Fix the problem by keeping a strong ref to that `GCancellable` around
    until the `ConnectionAttempt` is finished being destroyed.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #2687

 gio/gsocketclient.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
---
diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
index cd5aa074a1..8bcbdfa85d 100644
--- a/gio/gsocketclient.c
+++ b/gio/gsocketclient.c
@@ -1508,6 +1508,7 @@ typedef struct
   GSocketClientAsyncConnectData *data; /* unowned */
   GSource *timeout_source;
   GCancellable *cancellable;
+  GCancellable *task_cancellable;  /* (owned); this is equal to g_task_get_cancellable 
(ConnectionAttempt.data->task), but with a longer lifetime */
   gulong cancelled_id;
   grefcount ref;
 } ConnectionAttempt;
@@ -1536,7 +1537,8 @@ connection_attempt_unref (gpointer pointer)
       g_clear_object (&attempt->address);
       g_clear_object (&attempt->socket);
       g_clear_object (&attempt->connection);
-      g_cancellable_disconnect (g_task_get_cancellable (attempt->data->task), attempt->cancelled_id);
+      g_cancellable_disconnect (attempt->task_cancellable, attempt->cancelled_id);
+      g_clear_object (&attempt->task_cancellable);
       attempt->cancelled_id = 0;
       g_clear_object (&attempt->cancellable);
       g_clear_object (&attempt->proxy_addr);
@@ -2031,9 +2033,12 @@ g_socket_client_enumerator_callback (GObject      *object,
   data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
 
   if (g_task_get_cancellable (data->task))
-    attempt->cancelled_id =
-        g_cancellable_connect (g_task_get_cancellable (data->task), G_CALLBACK (on_connection_cancelled),
-                               g_object_ref (attempt->cancellable), g_object_unref);
+    {
+      attempt->task_cancellable = g_object_ref (g_task_get_cancellable (data->task));
+      attempt->cancelled_id =
+          g_cancellable_connect (attempt->task_cancellable, G_CALLBACK (on_connection_cancelled),
+                                 g_object_ref (attempt->cancellable), g_object_unref);
+    }
 
   g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
   g_debug ("GSocketClient: Starting TCP connection attempt");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]