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 514717 - memleak in Pad.set_blocked_async()
memleak in Pad.set_blocked_async()
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-python
git master
Other Linux
: Normal normal
: 0.10.15
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2008-02-06 10:38 UTC by Arek Korbik
Modified: 2009-02-22 19:14 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fix (2.03 KB, patch)
2008-02-10 10:01 UTC, Alessandro Decina
rejected Details | Review
Add gst_pad_set_blocked_async_full (4.64 KB, patch)
2008-11-10 22:44 UTC, Alessandro Decina
none Details | Review
Wrap gst_pad_set_blocked_async_full if available (4.97 KB, patch)
2008-11-10 22:45 UTC, Alessandro Decina
committed Details | Review
gst_pad_set_blocked_async_full + tests (11.16 KB, patch)
2008-11-14 17:31 UTC, Alessandro Decina
committed Details | Review

Description Arek Korbik 2008-02-06 10:38:57 UTC
Pad.set_blocked_async() never releases the passed callback function. It's quite visible if the function is a dynamic one defined in a closure.
Comment 1 Alessandro Decina 2008-02-10 10:01:07 UTC
Created attachment 104824 [details] [review]
Fix
Comment 2 Edward Hervey 2008-02-10 13:33:52 UTC
2008-02-10  Alessandro Decina  <alessandro@nnva.org>

	reviewed by: Edward Hervey  <edward.hervey@collabora.co.uk>
	* gst/gstpad.override:
	* testsuite/test_pad.py:
	Fix memleak in gst.Pad.set_blocked_async()
	Fixes #514717
	
Comment 3 Mark Nauwelaerts 2008-05-30 17:37:20 UTC
I am not sure if this introduced other problems, but I now (0.10.11) get segfault whose backtrace is very close to what has been changed here (see below; gdb may be a bit off given the O2 optimized code).

I am also not clear on why a Py_DECREF is needed here on py_user_data.
AFAIK, a pad's block callback can be called several times, so pad_block_callback_marshal can be called more than once with the same user_data.  In each case, py_user_data refcount is decreased by Py_DECREF, but I don't know where the refcount of py_user_data is correspondingly increased with each call [PyTuple_GetItem returns a borrowed reference, so it can't be there].
If there is indeed no increase of refcount, this decreasing eventually leads to a premature release of py_user_data.

On the other hand, indeed, if Py_DECREF is not used here, the callback function does not get released if one does not explicitly call Pad.set_blocked_async() with an empty handler.  But that seems to be due to the core not employing some sort of destroy_notify to inform when it is removing refs to the callback.

In any case, presence of Py_DECREF(py_user_data) seems to have a pretty good correspondence with the occurrence of segfaults (with only minute non-determinism).

(gdb) frame
  • #0 pad_block_callback_marshal
    at gstpad.override line 1345
  • #0 pad_block_callback_marshal
    at gstpad.override line 1345
  • #1 handle_pad_block
    at gstpad.c line 3373
  • #2 gst_pad_push_event
    at gstpad.c line 4109
  • #3 gst_proxy_pad_do_event
    at gstghostpad.c line 142
  • #4 gst_pad_send_event
    at gstpad.c line 4276
  • #5 gst_pad_push_event
    at gstpad.c line 4132
  • #6 gst_mpeg2dec_sink_event
    at gstmpeg2dec.c line 1251
  • #7 gst_pad_send_event
    at gstpad.c line 4276
  • #8 gst_pad_push_event
    at gstpad.c line 4132
  • #9 gst_multi_queue_loop
    at gstmultiqueue.c line 739
  • #10 gst_task_func
    at gsttask.c line 192
  • #11 ??
    from /usr/lib/libglib-2.0.so.0
  • #12 ??
  • #13 ??
  • #14 pthread_mutex_lock
    from /lib/libpthread.so.0
  • #15 ??
    from /usr/lib/libglib-2.0.so.0
  • #16 ??
  • #17 ??
  • #18 ??

Comment 4 Mark Nauwelaerts 2008-06-05 11:14:50 UTC
I am re-opening this is blocker for the upcoming release
(rather than a new bug, as it keeps the history).
If the comments above are about right, then the patch is probably to undo the previous patch.
If, however, I am quite simply going daft and missing a point somewhere, then this is easily closed again, and above report should probably go into another bug, but then I have no idea about the cause (or patch), at least for now.
Comment 5 Jan Schmidt 2008-06-11 09:16:59 UTC
Ping? Is anyone working on this?
Comment 6 Alessandro Decina 2008-06-12 10:52:28 UTC
I think Mark is right and this needs to  be reverted. The idea was that a pad_block callback could only be called once. This doesn't seem the case though, as the OBJECT_LOCK is released before calling the callback.
Comment 7 Edward Hervey 2008-06-12 11:12:20 UTC
2008-06-12  Edward Hervey  <edward.hervey@collabora.co.uk>

	* gst/gstpad.override:
	* testsuite/test_pad.py:
	Revert 2008-02-10  Alessandro Decina  <alessandro@nnva.org>
	Re-opens #514717

Comment 8 Arek Korbik 2008-09-09 16:45:26 UTC
I've just realized that the actual trace that Mark posted fails on the line just before the one that has been removed while reverting. With the new version after the revert, I still experience similar crashes as Mark, on:
  1345        Py_DECREF(args);
Comment 9 Alessandro Decina 2008-11-10 22:44:30 UTC
Created attachment 122363 [details] [review]
Add gst_pad_set_blocked_async_full
Comment 10 Alessandro Decina 2008-11-10 22:45:40 UTC
Created attachment 122364 [details] [review]
Wrap gst_pad_set_blocked_async_full if available
Comment 11 Alessandro Decina 2008-11-10 22:49:52 UTC
In the first patch I added gst_pad_set_blocked_async_full
so that it's possible to pass a GDestroyNotify to avoid the leak.
In the gst.Pad.set_blocked_async wrapper then I use _full if
available otherwise there's a fallback on the old implementation.
Comment 12 Alessandro Decina 2008-11-14 17:31:56 UTC
Created attachment 122673 [details] [review]
gst_pad_set_blocked_async_full + tests

We discussed this a bit with wtay on irc and he gave me some suggestions
(destroy user_data in gst_pad_dispose if necessary and don't call destroy
when resetting user_data to the same value). I also added some tests.

We also agreed in that the current implementation is broken when 
gst_pad_set_blocked_async (pad, state, ...) is called and GST_PAD_IS_BLOCKED (pad) == state. The only problem is that the behaviour is sort of documented in the API. Anyway, I added a test (disabled for the moment) which shows what I think the correct behaviour should be. If people think it can be changed, i'm going to enable the test and change the implementation.
Comment 13 Edward Hervey 2008-12-06 15:57:12 UTC
Shouldn't we move this bug to core (or at least create one that would block this bug) ?
Comment 14 Alessandro Decina 2008-12-08 12:11:09 UTC
Hum, basically I was going to commit this but I forgot.
If you think it needs more discussion then yeah, we should probably
create a core bug that blocks this one.
Comment 15 Edward Hervey 2009-02-22 19:03:10 UTC
commit d3940f520b140f62dd616baf3b50832eac8fe648
Author: Alessandro Decina <alessandro.d@gmail.com>
Date:   Sun Feb 22 20:01:05 2009 +0100

    GstPad: Add gst_pad_set_blocked_async_full
    
    This allows connecting a GDestroyNotify for when the callback is removed/replaced.
    Partially fixes #514717

Comment 16 Edward Hervey 2009-02-22 19:14:03 UTC
commit 4fadf0700ea010d82073526d2eb91650c9d1be1c
Author: Edward Hervey <bilboed@bilboed.com>
Date:   Sun Feb 22 20:08:54 2009 +0100

    gstbus.override: Allow using set_sync_handler with None as a parameter