From: Stian Selnes Date: Mon, 21 Sep 2015 11:58:51 +0000 (+0200) Subject: funnel: Fix racy state change X-Git-Tag: 1.6.1~19 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2c60b7eb1fc8851296e7bbb209663bb0c0e53f21;p=platform%2Fupstream%2Fgstreamer.git funnel: Fix racy state change Iterator may need to be resynced, for instance if pads are released during state change. got_eos should be protected by the object lock of the element, not of the pad, as is the case throughout the rest of the funnel code. https://bugzilla.gnome.org/show_bug.cgi?id=755343 --- diff --git a/plugins/elements/gstfunnel.c b/plugins/elements/gstfunnel.c index 80ba3a48e5..bf45db58db 100644 --- a/plugins/elements/gstfunnel.c +++ b/plugins/elements/gstfunnel.c @@ -429,10 +429,11 @@ reset_pad (const GValue * data, gpointer user_data) { GstPad *pad = g_value_get_object (data); GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad); + GstFunnel *funnel = user_data; - GST_OBJECT_LOCK (pad); + GST_OBJECT_LOCK (funnel); fpad->got_eos = FALSE; - GST_OBJECT_UNLOCK (pad); + GST_OBJECT_UNLOCK (funnel); } static GstStateChangeReturn @@ -451,9 +452,10 @@ gst_funnel_change_state (GstElement * element, GstStateChange transition) GstIteratorResult res; do { - res = gst_iterator_foreach (iter, reset_pad, NULL); + res = gst_iterator_foreach (iter, reset_pad, element); + if (res == GST_ITERATOR_RESYNC) + gst_iterator_resync (iter); } while (res == GST_ITERATOR_RESYNC); - gst_iterator_free (iter); if (res == GST_ITERATOR_ERROR) diff --git a/tests/check/elements/funnel.c b/tests/check/elements/funnel.c index 313dd48666..fa64a3a496 100644 --- a/tests/check/elements/funnel.c +++ b/tests/check/elements/funnel.c @@ -23,6 +23,7 @@ # include #endif +#include #include struct TestData @@ -372,6 +373,42 @@ GST_START_TEST (test_funnel_gap_event) GST_END_TEST; +GST_START_TEST (test_funnel_stress) +{ + GstHarness *h0 = gst_harness_new_with_padnames ("funnel", "sink_0", "src"); + GstHarness *h1 = gst_harness_new_with_element (h0->element, "sink_1", NULL); + GstHarnessThread *state, *req, *push0, *push1; + GstPadTemplate *templ = gst_element_class_get_pad_template ( + GST_ELEMENT_GET_CLASS (h0->element), "sink_%u"); + GstCaps *caps = gst_caps_from_string ("testcaps"); + GstBuffer *buf = gst_buffer_new (); + GstSegment segment; + + gst_segment_init (&segment, GST_FORMAT_TIME); + + state = gst_harness_stress_statechange_start (h0); + req = gst_harness_stress_requestpad_start (h0, templ, NULL, NULL, TRUE); + push0 = gst_harness_stress_push_buffer_start (h0, caps, &segment, buf); + push1 = gst_harness_stress_push_buffer_start (h1, caps, &segment, buf); + + gst_caps_unref (caps); + gst_buffer_unref (buf); + + /* test-length */ + g_usleep (G_USEC_PER_SEC * 1); + + gst_harness_stress_thread_stop (push1); + gst_harness_stress_thread_stop (push0); + gst_harness_stress_thread_stop (req); + gst_harness_stress_thread_stop (state); + + gst_harness_teardown (h1); + gst_harness_teardown (h0); +} + +GST_END_TEST; + + static Suite * funnel_suite (void) { @@ -382,6 +419,7 @@ funnel_suite (void) tcase_add_test (tc_chain, test_funnel_simple); tcase_add_test (tc_chain, test_funnel_eos); tcase_add_test (tc_chain, test_funnel_gap_event); + tcase_add_test (tc_chain, test_funnel_stress); suite_add_tcase (s, tc_chain); return s;