From dabcc3b459e14afce0d51a05637674ee913a56c2 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 15 Mar 2019 17:07:06 -0300 Subject: [PATCH] nlesource: Protect seeks from tear down Otherwise there is a race where we trigger the seek at the exact same time the composition is being teared down potentially leading to basesrc restarting its srcpad task which ends up being leaked. Fixes ges.playback.scrub_backward_seeking.test_title.audio_video.vorbis_theora_ogg and probably all its friends timeouting with the following stack trace: (gdb) t a a bt Thread 4 (Thread 0x7f5962acd700 (LWP 19997)): #0 0x00007f5976713efd in syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38 #1 0x00007f5976a9d3f3 in g_cond_wait (cond=cond@entry=0x7f5938125410, mutex=mutex@entry=0x7f59381253c8) at gthread-posix.c:1402 #2 0x00007f5976c9e26b in gst_task_func (task=0x7f59381253b0 [GstTask]) at ../subprojects/gstreamer/gst/gsttask.c:313 #3 0x00007f5976a7ecb3 in g_thread_pool_thread_proxy (data=) at gthreadpool.c:307 #4 0x00007f5976a7e2aa in g_thread_proxy (data=0x7f5954071d40) at gthread.c:784 #5 0x00007f59767ea58e in start_thread (arg=) at pthread_create.c:486 #6 0x00007f59767196a3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 Thread 3 (Thread 0x7f5963fff700 (LWP 19995)): #0 0x00007f597670e421 in __GI___poll (fds=0xe32da0, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29 #1 0x00007f5976a553a6 in g_main_context_poll (priority=, n_fds=2, fds=0xe32da0, timeout=, context=0xe31ff0) at gmain.c:4221 #2 0x00007f5976a553a6 in g_main_context_iterate (context=0xe31ff0, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3915 #3 0x00007f5976a55762 in g_main_loop_run (loop=0xe32130) at gmain.c:4116 #4 0x00007f59768db10a in gdbus_shared_thread_func (user_data=0xe31fc0) at gdbusprivate.c:275 #5 0x00007f5976a7e2aa in g_thread_proxy (data=0xe1b8a0) at gthread.c:784 #6 0x00007f59767ea58e in start_thread (arg=) at pthread_create.c:486 #7 0x00007f59767196a3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 Thread 2 (Thread 0x7f5968dcc700 (LWP 19994)): #0 0x00007f597670e421 in __GI___poll (fds=0xe1bcc0, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29 #1 0x00007f5976a553a6 in g_main_context_poll (priority=, n_fds=1, fds=0xe1bcc0, timeout=, context=0xe1b350) at gmain.c:4221 #2 0x00007f5976a553a6 in g_main_context_iterate (context=context@entry=0xe1b350, block=block@entry=1, dispatch=dispatch@entry=1, self=) at gmain.c:3915 #3 0x00007f5976a554d0 in g_main_context_iteration (context=0xe1b350, may_block=may_block@entry=1) at gmain.c:3981 #4 0x00007f5976a55521 in glib_worker_main (data=) at gmain.c:5861 #5 0x00007f5976a7e2aa in g_thread_proxy (data=0xe1b800) at gthread.c:784 #6 0x00007f59767ea58e in start_thread (arg=) at pthread_create.c:486 #7 0x00007f59767196a3 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 Thread 1 (Thread 0x7f5975df4fc0 (LWP 19993)): #0 0x00007f5976713efd in syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38 #1 0x00007f5976a9d3f3 in g_cond_wait (cond=cond@entry=0xe34020, mutex=0xe39b80) at gthread-posix.c:1402 #2 0x00007f5976a7f41c in g_thread_pool_free (pool=0xe34000, immediate=0, wait_=) at gthreadpool.c:776 #3 0x00007f5976c9f1ca in default_cleanup (pool=0xe256b0 [GstTaskPool]) at ../subprojects/gstreamer/gst/gsttaskpool.c:89 #4 0x00007f5976c9e32d in init_klass_pool (klass=) at ../subprojects/gstreamer/gst/gsttask.c:161 #5 0x00007f5976c9e502 in gst_task_cleanup_all () at ../subprojects/gstreamer/gst/gsttask.c:381 #6 0x00007f5976c214f4 in gst_deinit () at ../subprojects/gstreamer/gst/gst.c:1095 #7 0x000000000040394f in main (argc=6, argv=) at ../subprojects/gst-editing-services/tools/ges-launch.c:94 --- plugins/nle/nlesource.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/plugins/nle/nlesource.c b/plugins/nle/nlesource.c index 8671331466..3d64b096a4 100644 --- a/plugins/nle/nlesource.c +++ b/plugins/nle/nlesource.c @@ -58,6 +58,7 @@ struct _NleSourcePrivate GstPad *ghostedpad; /* Pad (to be) ghosted */ GstPad *staticpad; /* The only pad. We keep an extra ref */ + GMutex seek_lock; GstEvent *seek_event; gulong probeid; }; @@ -75,6 +76,8 @@ static void nle_source_dispose (GObject * object); static gboolean nle_source_control_element_func (NleSource * source, GstElement * element); +static GstStateChangeReturn nle_source_change_state (GstElement * element, + GstStateChange transition); static void nle_source_class_init (NleSourceClass * klass) @@ -95,6 +98,7 @@ nle_source_class_init (NleSourceClass * klass) "Wim Taymans , Edward Hervey "); gstelement_class->send_event = GST_DEBUG_FUNCPTR (nle_source_send_event); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (nle_source_change_state); parent_class = g_type_class_ref (NLE_TYPE_OBJECT); @@ -119,6 +123,7 @@ nle_source_init (NleSource * source) GST_OBJECT_FLAG_SET (source, NLE_OBJECT_SOURCE); source->element = NULL; source->priv = nle_source_get_instance_private (source); + g_mutex_init (&source->priv->seek_lock); GST_DEBUG_OBJECT (source, "Setting GstBin async-handling to TRUE"); g_object_set (G_OBJECT (source), "async-handling", TRUE, NULL); @@ -160,10 +165,12 @@ nle_source_dispose (GObject * object) priv->staticpad = NULL; } + g_mutex_lock (&priv->seek_lock); if (priv->seek_event) { gst_event_unref (priv->seek_event); priv->seek_event = NULL; } + g_mutex_unlock (&priv->seek_lock); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -412,7 +419,9 @@ nle_source_send_event (GstElement * element, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: + g_mutex_lock (&source->priv->seek_lock); source->priv->seek_event = event; + g_mutex_unlock (&source->priv->seek_lock); break; default: res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event); @@ -427,6 +436,7 @@ ghost_seek_pad (NleSource * source) { NleSourcePrivate *priv = source->priv; + g_mutex_lock (&priv->seek_lock); if (priv->seek_event) { GstEvent *seek_event = priv->seek_event; priv->seek_event = NULL; @@ -435,6 +445,7 @@ ghost_seek_pad (NleSource * source) GST_ELEMENT_ERROR (source, RESOURCE, SEEK, (NULL), ("Sending initial seek to upstream element failed")); } + g_mutex_unlock (&priv->seek_lock); GST_OBJECT_LOCK (source); if (priv->probeid) { @@ -511,3 +522,21 @@ nle_source_prepare (NleObject * object) return TRUE; } + +static GstStateChangeReturn +nle_source_change_state (GstElement * element, GstStateChange transition) +{ + NleSourcePrivate *priv = NLE_SOURCE (element)->priv; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_mutex_lock (&priv->seek_lock); + gst_clear_event (&priv->seek_event); + g_mutex_unlock (&priv->seek_lock); + break; + default: + break; + } + + return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); +}