decodebin2: Avoid deactivation races
authorEdward Hervey <edward@centricular.com>
Thu, 16 Nov 2017 05:39:41 +0000 (06:39 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Thu, 16 Nov 2017 05:44:10 +0000 (06:44 +0100)
Deactivating pads from two threads isn't 100% MT-safe. There is a
slim chance that the GstPadActivateFunc might be called twice with
the same values (in this case from the cleanup thread *and* from
the GstElement change_state function when going from PAUSED to READY).

In order to avoid that, call any existing cleanup function *before*
calling the parent change_state implementation on downwards state
changes.

gst/playback/gstdecodebin2.c

index 7741eee..a00efdb 100644 (file)
@@ -5372,6 +5372,17 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
       dbin->shutdown = TRUE;
       unblock_pads (dbin);
       DYN_UNLOCK (dbin);
+
+      /* Make sure we don't have cleanup races where
+       * we might be trying to deactivate pads (in the cleanup thread)
+       * at the same time as the default element deactivation
+       * (in PAUSED=>READY)  */
+      g_mutex_lock (&dbin->cleanup_lock);
+      if (dbin->cleanup_thread) {
+        g_thread_join (dbin->cleanup_thread);
+        dbin->cleanup_thread = NULL;
+      }
+      g_mutex_unlock (&dbin->cleanup_lock);
     default:
       break;
   }
@@ -5405,12 +5416,6 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
       dbin->buffering_status = NULL;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
-      g_mutex_lock (&dbin->cleanup_lock);
-      if (dbin->cleanup_thread) {
-        g_thread_join (dbin->cleanup_thread);
-        dbin->cleanup_thread = NULL;
-      }
-      g_mutex_unlock (&dbin->cleanup_lock);
     default:
       break;
   }