mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
ghostpad: fix race-condition while tearing down
An upstream query will take a ref on the internal proxypad, and can hence end up owning the last reference to that pad, causing a crash.
This commit is contained in:
parent
77502acabc
commit
e515aa06fe
2 changed files with 60 additions and 6 deletions
|
@ -506,13 +506,16 @@ gst_ghost_pad_dispose (GObject * object)
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
GST_OBJECT_LOCK (pad);
|
||||||
internal = GST_PROXY_PAD_INTERNAL (pad);
|
internal = GST_PROXY_PAD_INTERNAL (pad);
|
||||||
|
if (internal) {
|
||||||
gst_pad_set_activatemode_function (internal, NULL);
|
gst_pad_set_activatemode_function (internal, NULL);
|
||||||
|
|
||||||
|
GST_PROXY_PAD_INTERNAL (pad) = NULL;
|
||||||
|
GST_PROXY_PAD_INTERNAL (internal) = NULL;
|
||||||
|
|
||||||
/* disposes of the internal pad, since the ghostpad is the only possible object
|
/* disposes of the internal pad, since the ghostpad is the only possible object
|
||||||
* that has a refcount on the internal pad. */
|
* that has a refcount on the internal pad. */
|
||||||
gst_object_unparent (GST_OBJECT_CAST (internal));
|
gst_object_unparent (GST_OBJECT_CAST (internal));
|
||||||
GST_PROXY_PAD_INTERNAL (pad) = NULL;
|
}
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (pad);
|
||||||
|
|
||||||
|
@ -831,7 +834,12 @@ gst_ghost_pad_set_target (GstGhostPad * gpad, GstPad * newtarget)
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
|
g_return_val_if_fail (GST_IS_GHOST_PAD (gpad), FALSE);
|
||||||
g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
|
g_return_val_if_fail (GST_PAD_CAST (gpad) != newtarget, FALSE);
|
||||||
g_return_val_if_fail (newtarget != GST_PROXY_PAD_INTERNAL (gpad), FALSE);
|
|
||||||
|
if (newtarget == GST_PROXY_PAD_INTERNAL (gpad)) {
|
||||||
|
GST_WARNING_OBJECT (gpad, "Target has already been set to %s:%s",
|
||||||
|
GST_DEBUG_PAD_NAME (newtarget));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
GST_OBJECT_LOCK (gpad);
|
GST_OBJECT_LOCK (gpad);
|
||||||
internal = GST_PROXY_PAD_INTERNAL (gpad);
|
internal = GST_PROXY_PAD_INTERNAL (gpad);
|
||||||
|
|
|
@ -1321,6 +1321,51 @@ GST_START_TEST (test_activate_sink_switch_mode)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
static gboolean thread_running;
|
||||||
|
static gpointer
|
||||||
|
send_query_to_pad_func (GstPad * pad)
|
||||||
|
{
|
||||||
|
GstQuery *query = gst_query_new_latency ();
|
||||||
|
|
||||||
|
while (thread_running) {
|
||||||
|
gst_pad_peer_query (pad, query);
|
||||||
|
g_thread_yield ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_query_unref (query);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_stress_upstream_queries_while_tearing_down)
|
||||||
|
{
|
||||||
|
GThread *query_thread;
|
||||||
|
gint i;
|
||||||
|
GstPad *pad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||||
|
gst_pad_set_active (pad, TRUE);
|
||||||
|
|
||||||
|
thread_running = TRUE;
|
||||||
|
query_thread = g_thread_new ("queries",
|
||||||
|
(GThreadFunc) send_query_to_pad_func, pad);
|
||||||
|
|
||||||
|
for (i = 0; i < 1000; i++) {
|
||||||
|
GstPad *ghostpad = gst_ghost_pad_new ("ghost-sink", pad);
|
||||||
|
gst_pad_set_active (ghostpad, TRUE);
|
||||||
|
|
||||||
|
g_thread_yield ();
|
||||||
|
|
||||||
|
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghostpad), NULL);
|
||||||
|
gst_pad_set_active (pad, FALSE);
|
||||||
|
gst_object_unref (ghostpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_running = FALSE;
|
||||||
|
g_thread_join (query_thread);
|
||||||
|
|
||||||
|
gst_object_unref (pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_ghost_pad_suite (void)
|
gst_ghost_pad_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -1351,6 +1396,7 @@ gst_ghost_pad_suite (void)
|
||||||
tcase_add_test (tc_chain, test_activate_sink_and_src);
|
tcase_add_test (tc_chain, test_activate_sink_and_src);
|
||||||
tcase_add_test (tc_chain, test_activate_src_pull_mode);
|
tcase_add_test (tc_chain, test_activate_src_pull_mode);
|
||||||
tcase_add_test (tc_chain, test_activate_sink_switch_mode);
|
tcase_add_test (tc_chain, test_activate_sink_switch_mode);
|
||||||
|
tcase_add_test (tc_chain, test_stress_upstream_queries_while_tearing_down);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue