mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
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
This commit is contained in:
parent
0fbf1d3eb7
commit
2c60b7eb1f
2 changed files with 44 additions and 4 deletions
|
@ -429,10 +429,11 @@ reset_pad (const GValue * data, gpointer user_data)
|
||||||
{
|
{
|
||||||
GstPad *pad = g_value_get_object (data);
|
GstPad *pad = g_value_get_object (data);
|
||||||
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
|
GstFunnelPad *fpad = GST_FUNNEL_PAD_CAST (pad);
|
||||||
|
GstFunnel *funnel = user_data;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
GST_OBJECT_LOCK (funnel);
|
||||||
fpad->got_eos = FALSE;
|
fpad->got_eos = FALSE;
|
||||||
GST_OBJECT_UNLOCK (pad);
|
GST_OBJECT_UNLOCK (funnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -451,9 +452,10 @@ gst_funnel_change_state (GstElement * element, GstStateChange transition)
|
||||||
GstIteratorResult res;
|
GstIteratorResult res;
|
||||||
|
|
||||||
do {
|
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);
|
} while (res == GST_ITERATOR_RESYNC);
|
||||||
|
|
||||||
gst_iterator_free (iter);
|
gst_iterator_free (iter);
|
||||||
|
|
||||||
if (res == GST_ITERATOR_ERROR)
|
if (res == GST_ITERATOR_ERROR)
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <gst/check/gstharness.h>
|
||||||
#include <gst/check/gstcheck.h>
|
#include <gst/check/gstcheck.h>
|
||||||
|
|
||||||
struct TestData
|
struct TestData
|
||||||
|
@ -372,6 +373,42 @@ GST_START_TEST (test_funnel_gap_event)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
static Suite *
|
||||||
funnel_suite (void)
|
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_simple);
|
||||||
tcase_add_test (tc_chain, test_funnel_eos);
|
tcase_add_test (tc_chain, test_funnel_eos);
|
||||||
tcase_add_test (tc_chain, test_funnel_gap_event);
|
tcase_add_test (tc_chain, test_funnel_gap_event);
|
||||||
|
tcase_add_test (tc_chain, test_funnel_stress);
|
||||||
suite_add_tcase (s, tc_chain);
|
suite_add_tcase (s, tc_chain);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
Loading…
Reference in a new issue