timeline: No thread checking while disposing
authorThibault Saunier <tsaunier@igalia.com>
Wed, 13 May 2020 21:11:24 +0000 (17:11 -0400)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 19 May 2020 13:27:13 +0000 (13:27 +0000)
While this is not correct, we can't predict from what thread a
GstElement will be disposed as it might still be referenced by
a GstMessage somewhere which is freed by, any thread.

In this specific case we can assume that GES user will already have
let go his timeline reference and we should not avoid assert in that
specific case as it should be safe to let the timeline be destroyed
at that point.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/175>

ges/ges-internal.h
ges/ges-timeline.c
ges/ges-track.c

index 1a90282..eed5039 100644 (file)
@@ -106,6 +106,8 @@ ges_timeline_freeze_auto_transitions (GESTimeline * timeline, gboolean freeze);
 G_GNUC_INTERNAL GESAutoTransition *
 ges_timeline_get_auto_transition_at_end (GESTimeline * timeline, GESTrackElement * source);
 
+G_GNUC_INTERNAL gboolean ges_timeline_is_disposed (GESTimeline* timeline);
+
 G_GNUC_INTERNAL gboolean
 ges_timeline_edit (GESTimeline * timeline, GESTimelineElement * element,
     GList * layers, gint64 new_layer_priority, GESEditMode mode, GESEdge edge,
index d5ad187..e034c5c 100644 (file)
@@ -169,6 +169,7 @@ struct _GESTimelinePrivate
   GCond commited_cond;
 
   GThread *valid_thread;
+  gboolean disposed;
 
   GstStreamCollection *stream_collection;
 };
@@ -308,6 +309,12 @@ ges_timeline_set_property (GObject * object, guint property_id,
   }
 }
 
+gboolean
+ges_timeline_is_disposed (GESTimeline * timeline)
+{
+  return timeline->priv->disposed;
+}
+
 static void
 ges_timeline_dispose (GObject * object)
 {
@@ -315,6 +322,7 @@ ges_timeline_dispose (GObject * object)
   GESTimelinePrivate *priv = tl->priv;
   GList *tmp, *groups;
 
+  priv->disposed = TRUE;
   while (tl->layers) {
     GESLayer *layer = (GESLayer *) tl->layers->data;
     ges_timeline_remove_layer (GES_TIMELINE (object), layer);
@@ -2230,7 +2238,9 @@ ges_timeline_remove_layer (GESTimeline * timeline, GESLayer * layer)
 
   g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
   g_return_val_if_fail (GES_IS_LAYER (layer), FALSE);
-  CHECK_THREAD (timeline);
+
+  if (!timeline->priv->disposed)
+    CHECK_THREAD (timeline);
 
   GST_DEBUG ("timeline:%p, layer:%p", timeline, layer);
 
index cb98f21..8896c33 100644 (file)
@@ -1260,7 +1260,9 @@ ges_track_remove_element (GESTrack * track, GESTrackElement * object)
   g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
   g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
 
-  CHECK_THREAD (track);
+  if (!track->priv->timeline
+      || !ges_timeline_is_disposed (track->priv->timeline))
+    CHECK_THREAD (track);
 
   return remove_element_internal (track, object, TRUE);
 }