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 771326 - Fix memory leak: QCoreApplication::postEvent with DeactivateEvent never execute.
Fix memory leak: QCoreApplication::postEvent with DeactivateEvent never execute.
Status: RESOLVED INVALID
Product: GStreamer
Classification: Platform
Component: qt-gstreamer
git master
Other Linux
: Normal critical
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2016-09-12 21:07 UTC by Daniel Fussia
Modified: 2016-09-15 06:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch to fix memory leak: QCoreApplication::postEvent with DeactivateEvent never execute. (836 bytes, patch)
2016-09-12 21:07 UTC, Daniel Fussia
none Details | Review

Description Daniel Fussia 2016-09-12 21:07:08 UTC
Created attachment 335407 [details] [review]
Patch to fix memory leak: QCoreApplication::postEvent with DeactivateEvent never execute.

Hi,
 
I found a problem during restart the video in qt quick application using QtGstreamer.
In my pc this problem occur and so I don't have any critical problem, but on some i.MX6 board occurs memory leak in DMA allocation.
This problem occurs because 'DeactivateEvent' scheduled by 'postEvent' is never executed. Please see log at end: 'qt-gstreamer-fail.txt'.
There you can see that after 'Deactivating' it never writes the log 'Received deactivate event', simply this event is lost.
To fix this, I replaced method postEvent with sendEvent. Please see log at end: 'qt-gstreamer-ok.txt'.
After this fix, the 'Received deactivate event' always occurs after 'Deactivating'.
 
I created an application to make a test:
https://github.com/Danfx/qtteste/tree/master/QuickTest

Also a pull request of correction:
https://github.com/GStreamer/qt-gstreamer/pull/1

Please, comment.
 
Best Regards,
Daniel Fussia.
ICC - Inatel Competence Center

---------------- qt-gstreamer-fail.txt -------------------------
[fedora@localhost build-QuickTest-Desktop-Debug]$ GST_DEBUG=qt5videosink:6 ./QuickTest 
QML debugging is enabled. Only use this in a safe environment.
Stopping
Playing
0:00:02.357603234 31450 0x7fcb0c002b20 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink0> Activating
0:00:02.379428102 31450 0x7fcafc26f450 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/gstqtquick2videosink.cpp:233:gst_qt_quick2_video_sink_set_caps:<qtquick2videosink0> new caps video/x-raw, format=(string)I420, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)bt601, framerate=(fraction)0/1
0:00:02.397144289 31450      0x1eff4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:33:updateNode:<qtquick2videosink0> creating new VideoNode
0:00:02.397212117 31450      0x1eff4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:78:updateNode:<qtquick2videosink0> Recalculated paint areas: Frame size: (640 x 480), target area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), video area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), black1: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000), black2: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000)
Stopping
0:00:03.740933649 31450      0x1eff4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink0> Deactivating
Playing
0:00:04.033478734 31450 0x7fcb2001e450 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink1> Activating
0:00:04.055639390 31450 0x7fcb2001e370 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/gstqtquick2videosink.cpp:233:gst_qt_quick2_video_sink_set_caps:<qtquick2videosink1> new caps video/x-raw, format=(string)I420, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)bt601, framerate=(fraction)0/1
0:00:04.068494286 31450      0x1eff4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:33:updateNode:<qtquick2videosink1> creating new VideoNode
0:00:04.068560875 31450      0x1eff4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:78:updateNode:<qtquick2videosink1> Recalculated paint areas: Frame size: (640 x 480), target area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), video area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), black1: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000), black2: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000)
Stopping
0:00:06.882400786 31450      0x1eff4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink1> Deactivating
[fedora@localhost build-QuickTest-Desktop-Debug]$ 
----------------------------------------------------------------

---------------- qt-gstreamer-ok.txt -------------------------
[fedora@localhost build-QuickTest-Desktop-Debug]$ GST_DEBUG=qt5videosink:6 ./QuickTest 
QML debugging is enabled. Only use this in a safe environment.
Stopping
Playing
0:00:01.700519287 30893 0x7f2c14002720 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink0> Activating
0:00:01.719814604 30893 0x7f2c0c26acf0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/gstqtquick2videosink.cpp:233:gst_qt_quick2_video_sink_set_caps:<qtquick2videosink0> new caps video/x-raw, format=(string)I420, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)bt601, framerate=(fraction)0/1
0:00:01.735452508 30893      0x149a4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:33:updateNode:<qtquick2videosink0> creating new VideoNode
0:00:01.735518797 30893      0x149a4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:78:updateNode:<qtquick2videosink0> Recalculated paint areas: Frame size: (640 x 480), target area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), video area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), black1: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000), black2: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000)
Stopping
0:00:03.871434908 30893      0x149a4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink0> Deactivating
0:00:03.871636393 30893      0x149a4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:184:event:<qtquick2videosink0> Received deactivate event
Playing
0:00:03.883428503 30893      0x149a4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:33:updateNode:<qtquick2videosink1> creating new VideoNode
0:00:04.039055176 30893 0x7f2c34022ca0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink1> Activating
0:00:04.077142529 30893 0x7f2c34022b70 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/gstqtquick2videosink.cpp:233:gst_qt_quick2_video_sink_set_caps:<qtquick2videosink1> new caps video/x-raw, format=(string)I420, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, colorimetry=(string)bt601, framerate=(fraction)0/1
0:00:04.090962575 30893      0x149a4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/qtquick2videosinkdelegate.cpp:78:updateNode:<qtquick2videosink1> Recalculated paint areas: Frame size: (640 x 480), target area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), video area: (x: 0,000000, y: 0,000000, w: 640,000000, h: 480,000000), black1: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000), black2: (x: 0,000000, y: 0,000000, w: 0,000000, h: 0,000000)
Stopping
0:00:11.963099503 30893      0x149a4d0 INFO            qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:54:setActive:<qtquick2videosink1> Deactivating
0:00:11.963297834 30893      0x149a4d0 LOG             qt5videosink /home/fedora/env/qt-gstreamer/git/pc/qt-gstreamer/elements/gstqtvideosink/delegates/basedelegate.cpp:184:event:<qtquick2videosink1> Received deactivate event
[fedora@localhost build-QuickTest-Desktop-Debug]$ 
----------------------------------------------------------------
Comment 1 George Kiagiadakis 2016-09-15 06:33:12 UTC
I'm sorry, but this is wrong. There is a reason why the code calls postEvent() there instead of sendEvent(). 

With your patch, the event delivery becomes synchronous, which means that the thread that executes the element's state change will also deliver the event in the context of the state change. This is wrong because in GStreamer you cannot guarantee that the thread which executes the state change is the same as the main GUI thread, and in case the event is delivered in the wrong thread, the event loop will most likely crash (sendEvent() is *not* thread-safe). postEvent() on the other hand ensures that the event delivery happens in the correct thread, no matter which thread the event was sent from.

The real problem in your example is that your pipeline changes state to Null *after* the event loop terminates! The ~Player() destructor is called when main() terminates, after QCoreApplication::exec() has returned, so it is reasonable in this case for a leak to happen, since the event is posted to a non-existent event loop. It is generally a bad practice in Qt applications to allocate objects on the stack in main() because of that. Instead, allocate it on the heap and hook its destruction to the QCoreApplication::aboutToQuit() signal. This will ensure that everything cleans up properly before the event loop terminates.
Comment 2 George Kiagiadakis 2016-09-15 06:37:18 UTC
Oh and let me not forget that the async event delivery in this code exists in the first place exactly because the sink's drawing must happen in the GUI thread. This is the only way to guarantee the thread in which the drawing operations will execute.