gstpad: Avoid stream-dead-lock on deactivation
authorEdward Hervey <edward@centricular.com>
Tue, 16 Jan 2018 09:17:58 +0000 (10:17 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Tue, 16 Jan 2018 09:29:18 +0000 (10:29 +0100)
The following case can happen when two thread try to activate and
deactivate a pad at the same time:
T1: starts to deactivate, calls pre_activate(), sets in_activation
    to TRUE and carries on
T2: starts to activate, calls pre_activate(), in_activation is TRUE
    so it waits on the GCond
T1: calls post_activate(), tries to acquire the streaming lock ..
    but can't because T2 is currently holding it

With this patch, the deadlock will no longer happen but does not
solve the problem that:
T2: will resume activation of the pad, set the pad mode to the target
   one (PUSH or PULL) and eventually the streaming lock gets released.
T1: is able to finish calling post_activate() ... but ... the pad
   wasn't deactivated (T2 was the last one to "activate" the pad.

https://bugzilla.gnome.org/show_bug.cgi?id=792341

gst/gstpad.c

index 7137db2..99f445e 100644 (file)
@@ -1039,12 +1039,15 @@ post_activate (GstPad * pad, GstPadMode new_mode)
 {
   switch (new_mode) {
     case GST_PAD_MODE_NONE:
+      GST_OBJECT_LOCK (pad);
+      pad->priv->in_activation = FALSE;
+      g_cond_broadcast (&pad->priv->activation_cond);
+      GST_OBJECT_UNLOCK (pad);
+
       /* ensures that streaming stops */
       GST_PAD_STREAM_LOCK (pad);
       GST_DEBUG_OBJECT (pad, "stopped streaming");
       GST_OBJECT_LOCK (pad);
-      pad->priv->in_activation = FALSE;
-      g_cond_broadcast (&pad->priv->activation_cond);
       remove_events (pad);
       GST_OBJECT_UNLOCK (pad);
       GST_PAD_STREAM_UNLOCK (pad);