Async operations leveraging the GstBus

I am trying to leverage sending application messages on the GstBus to help synchronize application logic at various levels of a pipeline in an established application, migrating away from using GSignals in many cases to avoid interfering with the streaming thread (per the documentation, GstConf2023, etc.). From those discussions and the documentation, it sounded like messages being “posted up” from one bus to the other (cascade of GstBins) would not recurse on the same thread, but from the source code and now experience I have not found that to be true. For example, I expected this:

  1. Controller logic holds its own lock to prevent outside changes when it comes time to post a message about those changes.
  2. The child controller posts a message on the GstBin it manages and releases the lock.
  3. That GstBin “posts up” on its thread to its parent GstBin.
  4. The parent GstBin, on its thread, notifies the parent controller logic (via callback) that the message arrived on the parent’s GstBin bus.
  5. The parent controller needs some extra data from the child controller that wasn’t in the message and makes an API call on the child controller.
  6. The child controller uses the lock while retrieving the data and then releases it.

My expectation was that the above would work fine since the message arrival would be from a different thread than when it was sent, but my call stack says this was all recursive (and my read of the source code confirms this).

Is this a situation where gst_element_call_async is appropriate (use it when posting the message from the child logic to the element’s bus) or is there some other recommended mechanism/pattern?