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 768100 - ghostpad: invalid ref getting internal pad
ghostpad: invalid ref getting internal pad
Status: RESOLVED OBSOLETE
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
1.8.2
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2016-06-27 14:26 UTC by Miguel París Díaz
Modified: 2018-11-03 12:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
ghostpad: set internal ref of the internal pad to NULL (947 bytes, patch)
2016-06-27 14:31 UTC, Miguel París Díaz
reviewed Details | Review
ghostpad: manage internal ref holding the lock (2.07 KB, patch)
2016-06-27 14:31 UTC, Miguel París Díaz
none Details | Review
ghostpad: manage internal ref holding the lock (2.11 KB, patch)
2016-06-28 16:04 UTC, Miguel París Díaz
none Details | Review

Description Miguel París Díaz 2016-06-27 14:26:23 UTC
Hello,
I found an invalid reference usage while I was doing "massive testing".

In the GDB trace [gdb-1] we can see that the internal pad ref is not valid when the refcount is tried to be increased [ref-1]

Refs
[ref-1] https://github.com/Kurento/gstreamer/blob/2f41e7bc6a842044cb73bc0470601200575c378a/gst/gstghostpad.c#L224

GDB traces
[gdb-1]
  • #0 g_logv
    at /build/glib2.0-ajuDY6/glib2.0-2.46.1/./glib/gmessages.c line 324
  • #1 g_logv
    at /build/glib2.0-ajuDY6/glib2.0-2.46.1/./glib/gmessages.c line 1081
  • #2 g_log
    at /build/glib2.0-ajuDY6/glib2.0-2.46.1/./glib/gmessages.c line 1119
  • #3 g_return_if_fail_warning
  • #4 g_object_ref
    at /build/glib2.0-ajuDY6/glib2.0-2.46.1/./gobject/gobject.c line 3045
  • #5 gst_object_ref
    at gstobject.c line 256
  • #6 gst_proxy_pad_get_internal
    at gstghostpad.c line 224
  • #7 gst_proxy_pad_iterate_internal_links_default
    at gstghostpad.c line 94
  • #8 gst_pad_iterate_internal_links
    at gstpad.c line 2876
  • #9 gst_pad_forward
    at gstpad.c line 2915
  • #10 gst_pad_proxy_query_accept_caps
    at gstutils.c line 2539
  • #11 gst_pad_query_default
    at gstpad.c line 3062
  • #12 gst_pad_query_default
    at gstpad.c line 3338
  • #13 gst_pad_query
    at gstpad.c line 3922
  • #14 gst_pad_query_accept_caps
    at gstutils.c line 2926
  • #15 gst_pad_send_event_unchecked
    at gstpad.c line 5435
  • #16 gst_pad_send_event_unchecked
    at gstpad.c line 5567
  • #17 gst_pad_push_event_unchecked
    at gstpad.c line 5234
  • #18 push_sticky
    at gstpad.c line 3779
  • #19 events_foreach
    at gstpad.c line 601
  • #20 gst_pad_push_data
    at gstpad.c line 3836
  • #21 gst_pad_push_data
    at gstpad.c line 4407
  • #22 gst_pad_push
    at gstpad.c line 4548
  • #23 gst_tee_handle_data
    at gsttee.c line 605
  • #24 gst_tee_handle_data
    at gsttee.c line 685
  • #25 gst_tee_chain
    at gsttee.c line 768

Comment 1 Miguel París Díaz 2016-06-27 14:31:20 UTC
Created attachment 330438 [details] [review]
ghostpad: set internal ref of the internal pad to NULL

This patch should fix the bug.
Comment 2 Miguel París Díaz 2016-06-27 14:31:43 UTC
Created attachment 330439 [details] [review]
ghostpad: manage internal ref holding the lock
Comment 3 Sebastian Dröge (slomo) 2016-06-28 06:55:21 UTC
Review of attachment 330438 [details] [review]:

::: gst/gstghostpad.c
@@ +507,3 @@
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
+  GST_OBJECT_LOCK (internal);

Taking the object lock of the internal pad while we hold the one of the pad seems dangerous here, especially when seeing the gst_object_unparent() further below that might trigger going into another dispose().
Comment 4 Sebastian Dröge (slomo) 2016-06-28 06:58:13 UTC
Review of attachment 330439 [details] [review]:

::: gst/gstghostpad.c
@@ +590,3 @@
     goto parent_failed;
 
+  GST_OBJECT_LOCK (internal);

construct() is supposed to be called exactly after instantiation of the object, nothing else should have a reference to it other than this very thread that runs construct().

When does this lead to problems?

@@ +842,3 @@
   internal = GST_PROXY_PAD_INTERNAL (gpad);
 
+  if (newtarget == internal) {

This would be a programming error and should get a g_return_val_if_fail() or g_warning(). You should never set the internal pad as target of its ghostpad.
Comment 5 Sebastian Dröge (slomo) 2016-06-28 07:04:30 UTC
Review of attachment 330438 [details] [review]:

::: gst/gstghostpad.c
@@ +507,3 @@
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
+  GST_OBJECT_LOCK (internal);

In general your fix makes sense though, just needs careful checking if it can't lead to a deadlock (which I did not do)

@@ -511,2 @@
   /* disposes of the internal pad, since the ghostpad is the only possible object
    * that has a refcount on the internal pad. */

This comment also seems wrong :)
Comment 6 Miguel París Díaz 2016-06-28 15:39:30 UTC
Review of attachment 330438 [details] [review]:

::: gst/gstghostpad.c
@@ +507,3 @@
   internal = GST_PROXY_PAD_INTERNAL (pad);
 
+  GST_OBJECT_LOCK (internal);

The GST_PROXY_PAD_INTERNAL usage must be done holding the lock to avoid invalid reference.

I reviewed the patch and made some tests, but I agree with you to be reviewed carefully again.

@@ -511,2 @@
   /* disposes of the internal pad, since the ghostpad is the only possible object
    * that has a refcount on the internal pad. */

This comment is related with this other: https://github.com/Kurento/gstreamer/blob/2f41e7bc6a842044cb73bc0470601200575c378a/gst/gstghostpad.c#L589
Comment 7 Miguel París Díaz 2016-06-28 15:50:11 UTC
Review of attachment 330439 [details] [review]:

::: gst/gstghostpad.c
@@ +590,3 @@
     goto parent_failed;
 
+  GST_OBJECT_LOCK (internal);

gst_ghost_pad_construct is public, so it is not ensured to be only used from gst_ghost_pad_new_full.
Moreover:
 -  I prefer having the discipline of managing GST_PROXY_PAD_INTERNAL into the critical section
 - The lock is also held for the pad var

@@ +842,3 @@
   internal = GST_PROXY_PAD_INTERNAL (gpad);
 
+  if (newtarget == internal) {

I cannot use g_return_val_if_fail because this check is into the critical section and the lock must be released.
Do you want to use g_warning with a specific message?
Comment 8 Sebastian Dröge (slomo) 2016-06-28 15:54:15 UTC
(In reply to Miguel París Díaz from comment #7)
> Review of attachment 330439 [details] [review] [review]:
> 
> ::: gst/gstghostpad.c
> @@ +590,3 @@
>      goto parent_failed;
>  
> +  GST_OBJECT_LOCK (internal);
> 
> gst_ghost_pad_construct is public, so it is not ensured to be only used from
> gst_ghost_pad_new_full.
> Moreover:
>  -  I prefer having the discipline of managing GST_PROXY_PAD_INTERNAL into
> the critical section
>  - The lock is also held for the pad var

It's invalid usage of the API otherwise, but I agree that we should take the lock here for consistency reasons already. I was just wondering if you were getting a problem from that specific code too.

> @@ +842,3 @@
>    internal = GST_PROXY_PAD_INTERNAL (gpad);
>  
> +  if (newtarget == internal) {
> 
> I cannot use g_return_val_if_fail because this check is into the critical
> section and the lock must be released.
> Do you want to use g_warning with a specific message?

Or unlock inside the if and then do a g_return_val_if_fail() ;)
Comment 9 Miguel París Díaz 2016-06-28 16:01:59 UTC
(In reply to Sebastian Dröge (slomo) from comment #8)
> (In reply to Miguel París Díaz from comment #7)
> > Review of attachment 330439 [details] [review] [review] [review]:
> > 
> > ::: gst/gstghostpad.c
> > @@ +590,3 @@
> >      goto parent_failed;
> >  
> > +  GST_OBJECT_LOCK (internal);
> > 
> > gst_ghost_pad_construct is public, so it is not ensured to be only used from
> > gst_ghost_pad_new_full.
> > Moreover:
> >  -  I prefer having the discipline of managing GST_PROXY_PAD_INTERNAL into
> > the critical section
> >  - The lock is also held for the pad var
> 
> It's invalid usage of the API otherwise, but I agree that we should take the
> lock here for consistency reasons already. I was just wondering if you were
> getting a problem from that specific code too.

I don't think so, my problem should have happened by the code changed in the other commit.

> 
> > @@ +842,3 @@
> >    internal = GST_PROXY_PAD_INTERNAL (gpad);
> >  
> > +  if (newtarget == internal) {
> > 
> > I cannot use g_return_val_if_fail because this check is into the critical
> > section and the lock must be released.
> > Do you want to use g_warning with a specific message?
> 
> Or unlock inside the if and then do a g_return_val_if_fail() ;)

OK, I will do it!!
Comment 10 Miguel París Díaz 2016-06-28 16:04:43 UTC
Created attachment 330491 [details] [review]
ghostpad: manage internal ref holding the lock
Comment 11 Tim-Philipp Müller 2016-11-11 17:14:59 UTC
Patch was updated.
Comment 12 Tim-Philipp Müller 2017-12-01 00:40:53 UTC
Could you try with latest master? This might already have been fixed:

commit b63ed9e066e24e3fb110cff351fbf841a16c475f
Author: Tim-Philipp Müller <tim@centricular.com>
Date:   Fri Nov 24 09:53:41 2017 +0100

    ghostpad: return TRUE if target pad was already set
    
    The state is as it should be, so no reason to return
    FALSE really, everything's good.

commit 3203a10821ae0f05b42f7e2556a9869598e701c1
Author: Tim-Philipp Müller <tim@centricular.com>
Date:   Fri Nov 24 09:40:07 2017 +0100

    ghostpad: access internal pad with lock held

commit e515aa06fe9496674dbc31eb7de642ffbd2ac28d
Author: Havard Graff <havard.graff@gmail.com>
Date:   Thu Mar 30 09:17:08 2017 +0200

    ghostpad: fix race-condition while tearing down
    
    An upstream query will take a ref on the internal proxypad, and can
    hence end up owning the last reference to that pad, causing a crash.
Comment 13 GStreamer system administrator 2018-11-03 12:35:13 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/177.