From 88c6896fb9db7d61429d6305314d549c818545da Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 25 May 2010 19:17:44 +0200 Subject: [PATCH] gstbin: unlock _get_state() on error When an error message is received on the bus, mark the bin as being in the error state and unlock all current _get_state() calls with an error. Fixes #505770 --- gst/gstbin.c | 11 ++++++++++ tests/check/gst/gstbin.c | 46 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/gst/gstbin.c b/gst/gstbin.c index e1850c9e15..5a94c3a270 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -3002,6 +3002,17 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message) GST_MESSAGE_TYPE_NAME (message)); switch (type) { + case GST_MESSAGE_ERROR: + { + GST_OBJECT_LOCK (bin); + /* flag error */ + GST_DEBUG_OBJECT (bin, "got ERROR message, unlocking state change"); + GST_STATE_RETURN (bin) = GST_STATE_CHANGE_FAILURE; + GST_STATE_BROADCAST (bin); + GST_OBJECT_UNLOCK (bin); + + goto forward; + } case GST_MESSAGE_EOS: { gboolean eos; diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index badb0491a2..6b80d1db13 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -444,6 +444,51 @@ GST_START_TEST (test_watch_for_state_change) GST_END_TEST; +GST_START_TEST (test_state_change_error_message) +{ + GstElement *src, *sink, *bin; + GstBus *bus; + GstStateChangeReturn ret; + + bin = gst_element_factory_make ("bin", NULL); + fail_unless (bin != NULL, "Could not create bin"); + + bus = g_object_new (gst_bus_get_type (), NULL); + gst_element_set_bus (GST_ELEMENT_CAST (bin), bus); + + src = gst_element_factory_make ("fakesrc", NULL); + fail_if (src == NULL, "Could not create fakesrc"); + sink = gst_element_factory_make ("fakesink", NULL); + fail_if (sink == NULL, "Could not create fakesink"); + + /* add but don't link elements */ + gst_bin_add (GST_BIN (bin), sink); + gst_bin_add (GST_BIN (bin), src); + + /* change state, this should succeed */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* now wait, the streaming thread will error because the source is not + * linked. */ + ret = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (ret == GST_STATE_CHANGE_FAILURE); + + gst_bus_set_flushing (bus, TRUE); + + /* setting bin to NULL flushes the bus automatically */ + ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS); + + /* clean up */ + gst_object_unref (bus); + gst_object_unref (bin); +} + +GST_END_TEST; + + /* adding an element with linked pads to a bin unlinks the * pads */ GST_START_TEST (test_add_linked) @@ -1042,6 +1087,7 @@ gst_bin_suite (void) tcase_add_test (tc_chain, test_message_state_changed_child); tcase_add_test (tc_chain, test_message_state_changed_children); tcase_add_test (tc_chain, test_watch_for_state_change); + tcase_add_test (tc_chain, test_state_change_error_message); tcase_add_test (tc_chain, test_add_linked); tcase_add_test (tc_chain, test_add_self); tcase_add_test (tc_chain, test_iterate_sorted);