agent: Don't hold hard ref while removing stream
authorOlivier Crête <olivier.crete@collabora.com>
Fri, 8 May 2020 23:08:20 +0000 (19:08 -0400)
committerOlivier Crête <olivier.crete@ocrete.ca>
Mon, 18 May 2020 17:17:09 +0000 (17:17 +0000)
The timeout has a weak ref that should be enough.

agent/agent-priv.h
agent/agent.c
agent/discovery.c
agent/discovery.h

index eeb90dc..d6c488c 100644 (file)
@@ -150,6 +150,7 @@ struct _NiceAgent
   GSList *local_addresses;        /* list of NiceAddresses for local
                                     interfaces */
   GSList *streams;                /* list of Stream objects */
+  GSList *pruning_streams;        /* list of Streams current being shut down */
   GMainContext *main_context;     /* main context pointer */
   guint next_candidate_id;        /* id of next created candidate */
   guint next_stream_id;           /* id of next created candidate */
index f26f428..7bbf74a 100644 (file)
@@ -3415,7 +3415,7 @@ on_stream_refreshes_pruned (NiceAgent *agent, NiceStream *stream)
 
   nice_stream_close (agent, stream);
 
-  g_object_unref (agent);
+  agent->pruning_streams = g_slist_remove (agent->pruning_streams, stream);
 
   agent_unlock (agent);
 
@@ -3451,14 +3451,14 @@ nice_agent_remove_stream (
     return;
   }
 
-  g_object_ref (agent);
-
   /* note: remove items with matching stream_ids from both lists */
   conn_check_prune_stream (agent, stream);
   discovery_prune_stream (agent, stream_id);
   refresh_prune_stream_async (agent, stream,
       (NiceTimeoutLockedCallback) on_stream_refreshes_pruned);
 
+  agent->pruning_streams = g_slist_prepend (agent->pruning_streams, stream);
+
   /* Remove the stream and signal its removal. */
   agent->streams = g_slist_remove (agent->streams, stream);
 
@@ -5413,6 +5413,16 @@ nice_agent_dispose (GObject *object)
     agent->streams = g_slist_delete_link(agent->streams, agent->streams);
   }
 
+  while (agent->pruning_streams) {
+    NiceStream *s = agent->pruning_streams->data;
+
+    nice_stream_close (agent, s);
+    g_object_unref (s);
+
+    agent->pruning_streams = g_slist_delete_link(agent->pruning_streams,
+        agent->pruning_streams);
+  }
+
   while ((sig = g_queue_pop_head (&agent->pending_signals))) {
     free_queued_signal (sig);
   }
index f562bba..0abc7ec 100644 (file)
@@ -163,6 +163,11 @@ void refresh_free (NiceAgent *agent, CandidateRefresh *cand)
     g_clear_pointer (&cand->tick_source, g_source_unref);
   }
 
+  if (cand->destroy_source) {
+    g_source_destroy (cand->destroy_source);
+    g_source_unref (cand->destroy_source);
+  }
+
   if (cand->destroy_cb) {
     cand->destroy_cb (cand->destroy_cb_data);
   }
@@ -231,6 +236,10 @@ static gboolean refresh_remove_async (NiceAgent *agent, gpointer pointer)
     cand->timer_source = NULL;
   }
 
+  g_source_destroy (cand->destroy_source);
+  g_source_unref (cand->destroy_source);
+  cand->destroy_source = NULL;
+
   username = (uint8_t *)cand->candidate->turn->username;
   username_len = (size_t) strlen (cand->candidate->turn->username);
   password = (uint8_t *)cand->candidate->turn->password;
@@ -297,7 +306,6 @@ static void refresh_prune_async (NiceAgent *agent, GSList *refreshes,
 
   for (it = refreshes; it; it = it->next) {
     CandidateRefresh *cand = it->data;
-    GSource *timeout_source = NULL;
 
     if (cand->disposing)
       continue;
@@ -307,11 +315,9 @@ static void refresh_prune_async (NiceAgent *agent, GSList *refreshes,
     cand->destroy_cb = (GDestroyNotify) on_refresh_removed;
     cand->destroy_cb_data = data;
 
-    agent_timeout_add_with_context( agent, &timeout_source,
-        "TURN refresh remove async", timeout,
-        refresh_remove_async, cand);
+    agent_timeout_add_with_context(agent, &cand->destroy_source,
+        "TURN refresh remove async", timeout, refresh_remove_async, cand);
 
-    g_source_unref (timeout_source);
     ++data->items_to_free;
   }
 
index 3ef99b2..fd1dfe4 100644 (file)
@@ -82,6 +82,7 @@ typedef struct
   gboolean disposing;
   GDestroyNotify destroy_cb;
   gpointer destroy_cb_data;
+  GSource *destroy_source;
 } CandidateRefresh;
 
 void refresh_free (NiceAgent *agent, CandidateRefresh *refresh);