After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 631580 - Race in all the pad functions that don't require the pad to be active
Race in all the pad functions that don't require the pad to be active
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
git master
Other Linux
: Normal normal
: 0.11.x
Assigned To: GStreamer Maintainers
GStreamer Maintainers
: 638844 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2010-10-07 04:59 UTC by Olivier Crête
Modified: 2012-05-18 08:50 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch to add a sleep() to acceptcaps (566 bytes, text/plain)
2010-10-07 05:00 UTC, Olivier Crête
  Details
test program (669 bytes, text/plain)
2010-10-07 05:03 UTC, Olivier Crête
  Details
pad: Add PARENT_REQUIRED flag and do not call functions if it is set and not parent is set (16.38 KB, patch)
2011-04-11 14:21 UTC, Olivier Crête
none Details | Review
element: Make regular element pads require a parent for callbacks (2.18 KB, patch)
2011-04-11 14:21 UTC, Olivier Crête
reviewed Details | Review
ghostpad: Make sure the ghostpad don't call their proxypad if the parent is no longer set (841 bytes, patch)
2011-04-11 14:21 UTC, Olivier Crête
reviewed Details | Review
pad: Pass the parent to callback functions (20.82 KB, patch)
2011-04-11 14:27 UTC, Olivier Crête
reviewed Details | Review
pad: Add PARENT_REQUIRED flag and do not call functions if it is set and not parent is set (16.49 KB, patch)
2011-04-11 15:38 UTC, Olivier Crête
reviewed Details | Review

Description Olivier Crête 2010-10-07 04:59:24 UTC
There is a race that can happen if a pad function (like getcaps or acceptcaps) is called while the object is being removed, leading to a segfault.

Attached is a example that reproduces the problem (along with a patch to gstpad.c to add a sleep() to make it reproduceable easily).
Comment 1 Olivier Crête 2010-10-07 05:00:02 UTC
Created attachment 171875 [details]
patch to add a sleep() to acceptcaps
Comment 2 Olivier Crête 2010-10-07 05:03:08 UTC
Created attachment 171876 [details]
test program

I guess the solution in the "easy" solution is to verify the return value of gst_pad_get_parent() everywhere in the tree...

Another solution would be change GstPad to only hold a ref to the parent of the pad while calling the functions that don't require the pad to be active, and not call them if there is no parent and one was ever set.
Comment 3 Olivier Crête 2011-01-06 17:36:06 UTC
*** Bug 638844 has been marked as a duplicate of this bug. ***
Comment 4 Sebastian Dröge (slomo) 2011-04-08 14:41:43 UTC
Copying my comment from bug #646566 here, which essentially seems to be what Olivier and Wim want to have too:

IMHO the best solution for this would be to
a) add a GstObject *parent parameter to all pad callbacks and
b) add a flag to GstPad that you don't want to have your callback called if
there's no parent (and by default that flag is disabled)

For this we have to wait until 0.11 though because it's an API change.

b) might be possible to do in 0.10 by taking a reference of the parent before
calling the callbacks
Comment 5 Olivier Crête 2011-04-11 14:21:33 UTC
Created attachment 185702 [details] [review]
pad: Add PARENT_REQUIRED flag and do not call functions if it is set and not parent is set

This is the first step to prevent a possible race where a function is called after it has
been removed from its parent element.
Comment 6 Olivier Crête 2011-04-11 14:21:38 UTC
Created attachment 185703 [details] [review]
element: Make regular element pads require a parent for callbacks
Comment 7 Olivier Crête 2011-04-11 14:21:42 UTC
Created attachment 185704 [details] [review]
ghostpad: Make sure the ghostpad don't call their proxypad if the parent is no longer set
Comment 8 Olivier Crête 2011-04-11 14:27:19 UTC
Created attachment 185705 [details] [review]
pad: Pass the parent to callback functions

This patch is 0.11 material, although there are different solutions that we could use in 0.10:

1. Rename the function prototypes to ...Full and add a set of gst_pad_set_xfunc_full methods to set it and make the current ones just wrappers that typecast the parent-less methods into the parented ones. Then we just need to update all the plugins to take the parent from the parameter instead of fetching it.

2. We could add a GPrivate (thread local storage) and store the current parent inside it at the beginning of a callback (and keep a ref until we return from the callback). Then modify gst_object_get_parent() to return the value from the TLS if it's set.. That said, this wouldnt work with people using GST_{PAD,OBJECT}_PARENT .. and about half of the current plugins do

3. We could add some kind of queue for gst_object_set_parent() and "lock" the parent into place until all callbacks returns and only then actually set it. This would require zero changes to the current plugins, but I'm afraid of the side-effects (and it's also quite an ugly solution).
Comment 9 Sebastian Dröge (slomo) 2011-04-11 14:55:07 UTC
Review of attachment 185702 [details] [review]:

::: gst/gstpad.c
@@ +4275,3 @@
+      (parent = gst_pad_get_parent (pad)) == NULL) {
+    GST_PAD_STREAM_UNLOCK (pad);
+    return GST_FLOW_NOT_LINKED;

You should probably unref the buffer/event here and return WRONG_STATE instead of NOT_LINKED

@@ +4758,3 @@
+  if (GST_PAD_IS_PARENT_REQUIRED (pad) &&
+      (parent = gst_pad_get_parent (pad)) == NULL) {
+    return GST_FLOW_NOT_LINKED;

Same here

@@ +4887,3 @@
+  if (GST_PAD_IS_PARENT_REQUIRED (pad) &&
+      (parent = gst_pad_get_parent (pad)) == NULL) {
+    return GST_FLOW_NOT_LINKED;

And here
Comment 10 Sebastian Dröge (slomo) 2011-04-11 14:56:40 UTC
Except the last patch this could all be done in 0.10 already, the last patch requires changes *everywhere* though.
Comment 11 Olivier Crête 2011-04-11 15:38:08 UTC
Created attachment 185723 [details] [review]
pad: Add PARENT_REQUIRED flag and do not call functions if it is set and not parent is set

This is the first step to prevent a possible race where a function is called after it has
been removed from its parent element.
Comment 12 Olivier Crête 2011-04-11 15:39:10 UTC
(In reply to comment #10)
> Except the last patch this could all be done in 0.10 already, the last patch
> requires changes *everywhere* though.

But having the first patches without the last patch is not so useful because the pad parent could be NULLed between checking in gstpad.c and the element actually trying to read it.
Comment 13 Sebastian Dröge (slomo) 2011-04-11 15:48:43 UTC
(In reply to comment #12)
> (In reply to comment #10)
> > Except the last patch this could all be done in 0.10 already, the last patch
> > requires changes *everywhere* though.
> 
> But having the first patches without the last patch is not so useful because
> the pad parent could be NULLed between checking in gstpad.c and the element
> actually trying to read it.

Oh, right. The parent could still be unset although the pad holds a reference to it. Nevermind...
Comment 14 Sebastian Dröge (slomo) 2011-04-13 14:41:55 UTC
I'd say that this is fine for 0.11 but let's wait for Wim to comment first :) Also it will be a lot of work to change all existing elements
Comment 15 Sebastian Dröge (slomo) 2011-04-15 16:48:51 UTC
While we're changing all the pad functions we could as well add a user_data and GDestroyNotify parameter to them. g-i likes to have this :)
Comment 16 Olivier Crête 2011-04-15 16:54:07 UTC
add a different one for each callback ?
Comment 17 Sebastian Dröge (slomo) 2011-04-15 16:59:30 UTC
Yes, e.g.

gst_pad_set_chain_function (pad, func, user_data, destroy_notify)
Comment 18 Wim Taymans 2012-05-18 08:50:22 UTC
Implemented in 0.11.