[Bug 728502] New: ximagesrc has a serious shmem leak
GStreamer (bugzilla.gnome.org)
bugzilla at gnome.org
Fri Apr 18 06:56:55 PDT 2014
https://bugzilla.gnome.org/show_bug.cgi?id=728502
GStreamer | gst-plugins-good | 0.10.0
Summary: ximagesrc has a serious shmem leak
Classification: Platform
Product: GStreamer
Version: 0.10.0
OS/Version: All
Status: UNCONFIRMED
Severity: major
Priority: Normal
Component: gst-plugins-good
AssignedTo: gstreamer-bugs at lists.freedesktop.org
ReportedBy: alex at stunpix.com
QAContact: gstreamer-bugs at lists.freedesktop.org
GNOME version: ---
Created an attachment (id=274672)
View: https://bugzilla.gnome.org/attachment.cgi?id=274672
Review: https://bugzilla.gnome.org/review?bug=728502&attachment=274672
ximagesrc shmem leak patch
Seems I found quite old ximagesrc leak that, I suppose, affects all platforms
since 0.10 (or maybe earlier). Here is description of how I discovered it and
some technical background about the bug.
For my arm board with Ubuntu 12.04 I wrote an app that captures a desktop,
encodes video to h264 and streams it to server. Everything went good until I
noticed that app always got killed by system within one or two hours since it
was started. I began to suspect oom_killer. After hours of memory monitoring I
detected that both resident and virtual memory are constantly growing. Most
growing was a virtual memory. By disabling all elements in pipeline I found a
minimal pipeline that leaks:
gst-launch ximagesrc ! queue ! fakesrc
Depending on amount of memory in your system you'll get 'Killed' message after
running this simple pipeline.
I tested this pipeline on following platforms:
* ubuntu 12.04 arm + gstreamer0.10
* fresh archlinux x86_64 + gstreamer1.0
* ubuntu 13.10 x86_64 + gstreamer0.10/1.0
All these distros were affected. One note about ubuntu 13.10 x86_64: it leaks
with much slower rates than other tested distros, but also leaks. I don't know
why, but this is a fact. As I said, I suppose that all other platforms are also
affected, since this bug isn't platform specific.
How to measure. You need to run something that changes the desktop constantly
(looped animated gif for instance). After that you need to run pipeline and
then run oom_score checker:
cat /proc/$(pidof gst-launch-0.10)/oom_score
you'll notice that score is growing: from 3-5 to 15-20 within few minutes. On
my arm system with 2Gb ram it could take up to 1 hour to reach score ~500 when
process is killed by system.
Next measurement: what is leaking. If we'll run a command:
cat /proc/$(pidof gst-launch-0.10)/maps | grep SYSV0
we will see something like this:
41d00000-42084000 rw-s 00000000 00:04 316244015 /SYSV00000000 (deleted)
42114000-42498000 rw-s 00000000 00:04 316276788 /SYSV00000000 (deleted)
43000000-43384000 rw-s 00000000 00:04 316309558 /SYSV00000000 (deleted)
4340b000-4378f000 rw-s 00000000 00:04 316342327 /SYSV00000000 (deleted)
4378f000-43b13000 rw-s 00000000 00:04 316375096 /SYSV00000000 (deleted)
43b3e000-43ec2000 rw-s 00000000 00:04 316407866 /SYSV00000000 (deleted)
43f22000-442a6000 rw-s 00000000 00:04 316440636 /SYSV00000000 (deleted)
442f7000-4467b000 rw-s 00000000 00:04 316506174 /SYSV00000000 (deleted)
44738000-44abc000 rw-s 00000000 00:04 316538943 /SYSV00000000 (deleted)
These records are shared memory blocks occupied by the process. After several
minutes you'll see many of them. They aren't freed and counted by system as
used. In normal conditions there should be 2-3 such blocks.
Why this happens. An ximagesrc element uses XShm extension (if available in
system) to get desktop shots. Each such image (gstbuffer actually) has a memory
shared with X server. Once pipeline frees buffer, it returned to ximagesrc and
pushed into pool of unused buffers. Each time when element is asked for a new
frame, it takes from pool first unused buffer and deletes all other buffers.
Here is piece of code responsible for that:
while (ximagesrc->buffer_pool != NULL) {
ximage = ximagesrc->buffer_pool->data;
if ((ximage->width != ximagesrc->width) ||
(ximage->height != ximagesrc->height)) {
gst_ximage_buffer_free (ximage);
}
ximagesrc->buffer_pool = g_slist_delete_link (ximagesrc->buffer_pool,
ximagesrc->buffer_pool);
}
There only one issue: g_slist_delete_link() only removes item from linked list,
frees memory used by slist record, but it doesn't unrefs the buffer which it
holds. Buffer lost, shmem not freed as well. Not detectable by valgrind.
Patch with fix for 0.10.31 attached.
Any comments are appreciated.
--
Configure bugmail: https://bugzilla.gnome.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.
More information about the gstreamer-bugs
mailing list