validate: scenario: Fix race condition when ignoring EOS

The part of the code that is commented with:

```
  /* gst_validate_action_set_done() does not finish the action
    * immediately. Instead, it posts a task to the main thread to do most
    * of the work in _action_set_done().
    *
    * While the EOS handling lock guarantees that if an action had to call
    * gst_validate_action_set_done() it has done so, it does not guarantee
    * that _action_set_done() has been called.
    *
    * Is it possible that this handler is run before _action_set_done(), so
    * we check at this point for actions that have a pending_set_done and
    * call it before continuing. */
```

was not being executed in the case where the scenario was 'ignoring EOS'
while it was also required.

Also fix potential use after free in that specific code path.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9014>
This commit is contained in:
Thibault Saunier 2025-03-31 11:10:12 -03:00 committed by GStreamer Marge Bot
parent 8ff0a1c132
commit d0b2e6cb68

View File

@ -5199,11 +5199,6 @@ handle_bus_message (MessageData * d)
GstValidateActionType *stop_action_type;
GstStructure *s;
if (!is_error && priv->ignore_eos) {
GST_INFO_OBJECT (scenario, "Got EOS but ignoring it!");
goto done;
}
if (is_error && priv->allow_errors) {
#ifndef GST_DISABLE_GST_DEBUG
GError *err = NULL;
@ -5254,17 +5249,25 @@ handle_bus_message (MessageData * d)
* Is it possible that this handler is run before _action_set_done(), so
* we check at this point for actions that have a pending_set_done and
* call it before continuing. */
GList *actions = g_list_copy (priv->actions);
GList *actions = g_list_copy_deep (priv->actions,
(GCopyFunc) (gst_validate_action_ref), NULL);
GList *i;
for (i = actions; i; i = i->next) {
GstValidateAction *action = (GstValidateAction *) i->data;
if (action->priv->pending_set_done)
_action_set_done (action);
}
g_list_free (actions);
g_list_free_full (actions, (GDestroyNotify) gst_validate_action_unref);
}
if (!is_error) {
if (priv->ignore_eos) {
GST_INFO_OBJECT (scenario,
"Got EOS but ignoring it, executing next action?");
GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK (scenario);
goto done;
}
priv->got_eos = TRUE;
if (priv->wait_message_action) {