gst-validate-scenario: Add GST_VALIDATE_SCENARIO_EOS_HANDLING_LOCK

There was a race in appsrc-push when the pushed buffer caused an EOS.
The EOS event could be handled by the main thread, finishing the test
while the action, executing in the streaming thread, has not finished
yet.

A mutex is now introduced to add mutual exclusion for the two threads so
that an EOS does not cause the termination of the test while the action
is still going.
This commit is contained in:
Alicia Boya García 2019-02-09 01:16:31 +01:00 committed by Thibault Saunier
parent 5a2e2d5001
commit 1d4801d679
2 changed files with 27 additions and 2 deletions

View file

@ -2569,9 +2569,14 @@ appsrc_push_chain_wrapper (GstPad * pad, GstObject * parent, GstBuffer * buffer,
gpointer * user_data, gboolean * remove_wrapper) gpointer * user_data, gboolean * remove_wrapper)
{ {
GstValidateAction *action = (GstValidateAction *) user_data; GstValidateAction *action = (GstValidateAction *) user_data;
GstFlowReturn ret = pad->chainfunc (pad, parent, buffer); GstValidateScenario *scenario = gst_validate_action_get_scenario (action);
GstFlowReturn ret;
GST_VALIDATE_SCENARIO_EOS_HANDLING_LOCK (scenario);
ret = pad->chainfunc (pad, parent, buffer);
gst_validate_action_set_done (action); gst_validate_action_set_done (action);
*remove_wrapper = TRUE; *remove_wrapper = TRUE;
GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK (scenario);
g_object_unref (scenario);
return ret; return ret;
} }
@ -3015,6 +3020,8 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
GstValidateActionType *stop_action_type; GstValidateActionType *stop_action_type;
GstStructure *s; GstStructure *s;
GST_VALIDATE_SCENARIO_EOS_HANDLING_LOCK (scenario);
if (!is_error) { if (!is_error) {
priv->got_eos = TRUE; priv->got_eos = TRUE;
if (priv->message_type) { if (priv->message_type) {
@ -3023,6 +3030,7 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
GST_DEBUG_OBJECT (scenario, GST_DEBUG_OBJECT (scenario,
"Waiting for a message and got a next action" "Waiting for a message and got a next action"
" to execute, letting it a chance!"); " to execute, letting it a chance!");
GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK (scenario);
goto done; goto done;
} else { } else {
/* Clear current message wait if waiting for EOS */ /* Clear current message wait if waiting for EOS */
@ -3094,6 +3102,7 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
gst_validate_execute_action (stop_action_type, stop_action); gst_validate_execute_action (stop_action_type, stop_action);
gst_mini_object_unref (GST_MINI_OBJECT (stop_action)); gst_mini_object_unref (GST_MINI_OBJECT (stop_action));
GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK (scenario);
break; break;
} }
case GST_MESSAGE_BUFFERING: case GST_MESSAGE_BUFFERING:

View file

@ -254,9 +254,25 @@ struct _GstValidateScenario
/*< private >*/ /*< private >*/
GstValidateScenarioPrivate *priv; GstValidateScenarioPrivate *priv;
gpointer _gst_reserved[GST_PADDING + 1]; union {
gpointer _gst_reserved[GST_PADDING + 1];
struct {
GMutex eos_handling_lock;
} abi;
} ABI;
}; };
/* Some actions may trigger EOS during their execution. Unlocked this
* could cause a race condition as the main thread may terminate the test
* in response to the EOS message in the bus while the action is still
* going in a different thread.
* To avoid this, the handling of the EOS message is protected with this
* lock. Actions expecting to cause an EOS can hold the lock for their
* duration so that they are guaranteed to finish before the EOS
* terminates the test. */
#define GST_VALIDATE_SCENARIO_EOS_HANDLING_LOCK(scenario) (g_mutex_lock(&(scenario)->ABI.abi.eos_handling_lock))
#define GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK(scenario) (g_mutex_unlock(&(scenario)->ABI.abi.eos_handling_lock))
GST_VALIDATE_API GST_VALIDATE_API
GType gst_validate_scenario_get_type (void); GType gst_validate_scenario_get_type (void);