Talk:V4L Test Suite
It seems the 2 V4L2 examples (capture.c and vivi.c) don't play well with each other. I am not really sure where to post about this, so I will start here and move it to the appropriate place once I find it. so far http://bugzilla.kernel.org seems the most likely. I am dumping my notes on this page to try to keep the point of the article page from getting buried.
Bugs in Examples
capture.c and vivi.c are V4L2 examples:
capture: "Video for Linux Two API Specification: Revision 0.24 Appendix B. Video Capture Example"
vivi: "It is intended to be a working example code for current V4L2 Driver and Stub driver to facilitate the implementation of new video drivers.
They don't play well with each other. There is a memory leak, and I think vivi is telling capture to use a buffer mode that isn't valid - I call this "capabilities mismatch" but I am not really sure what the problem is.
Summary
detailed report: "vivi memory leak = kernel panic" https://bugs.launchpad.net/ubuntu/+source/linux/+bug/294951
memory leak
sudo modprobe vivi gcc capture.c -g -o capture valgrind ./capture --userp -d /dev/video1 ==17153== malloc/free: in use at exit: 2,457,632 bytes in 5 blocks.
capabilities mismatch
./capture --userp -d /dev/video1 VIDIOC_QBUF error 22, Invalid argument
Detail
setup for both: (capture.c is the original, same problem with capture_example.c, see URL above)
wget http://www.linuxtv.org/downloads/video4linux/API/V4L2_API/v4l2spec/capture.c gcc capture.c -g -o capture sudo modprobe vivi dmesg | grep /dev/video1 [ 1015.491550] vivi: V4L2 device registered as /dev/video1
memory leak
# memleak.sh # runs capture to cause "Cannot allocate memory" # and logs /proc/meminfo along the way set -x sudo modprobe vivi dmesg|grep vivi # make sure the above grep matchs: DEV=/dev/video0 if [ -d proc ]; then # wipe out previous run rm -f proc/meminfo* else # make a place to log proc/meminfo mkdir proc fi # 0.0 = start let a=0 cp /proc/meminfo proc/meminfo$a.0.txt # loop until "Cannot allocate memory" while true; do ((a+=1)) # run using valid params, therefore should not error. ./capture --read -d $DEV # unless something has sucked all the memory from somewhere. if [ "0" != "$?" ]; then break; fi # shouldn't be anything interesting, but log the state, just to be sure. cp /proc/meminfo proc/meminfo$a.1.txt # run with unsupported buffer mode ./capture --userp -d $DEV # which didn't release memory from who knows where, so log the state: cp /proc/meminfo proc/meminfo$a.2.txt done # x.3 = final state. should be about the same as x.2 cp /proc/meminfo proc/meminfo$a.3.txt
resulting data: http://spreadsheets.google.com/ccc?key=pIfz0wOzPtW1-oZkXXbvcLA&hl=en
The runaways: HighFree go from 72608 to 252 VmallocUsed from 6440 to 109724 VmallocChunk from 103620 to 336
Using valgrind (a suite of tools for debugging and profiling programs)
valgrind -v --leak-check=full --show-reachable=yes ./capture --userp -d /dev/video1 ==5166== Memcheck, a memory error detector. ==5166== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al. ==5166== Using LibVEX rev 1854, a library for dynamic binary translation. ==5166== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP. ==5166== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation framework. ==5166== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al. ==5166== --5166-- Command line --5166-- ./capture --5166-- --userp --5166-- -d --5166-- /dev/video1 --5166-- Startup, with flags: --5166-- --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp --5166-- -v --5166-- --leak-check=full --5166-- --show-reachable=yes --5166-- Contents of /proc/version: --5166-- Linux version 2.6.27-7-generic (buildd@palmer) (gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu11) ) #1 SMP Thu Oct 30 04:18:38 UTC 2008 --5166-- Arch and hwcaps: X86, x86-sse1-sse2 --5166-- Page sizes: currently 4096, max supported 4096 --5166-- Valgrind library directory: /usr/lib/valgrind --5166-- Reading syms from /lib/ld-2.8.90.so (0x4000000) --5166-- Reading debug info from /lib/ld-2.8.90.so... --5166-- ... CRC mismatch (computed 371b8ee6 wanted cc0a418a) --5166-- Reading debug info from /usr/lib/debug/lib/ld-2.8.90.so... --5166-- Reading syms from /home/juser/vga2usb/v4l.org/examples/capture (0x8048000) --5166-- Reading syms from /usr/lib/valgrind/x86-linux/memcheck (0x38000000) --5166-- object doesn't have a dynamic symbol table --5166-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp --5166-- Reading suppressions file: /usr/lib/valgrind/default.supp --5166-- REDIR: 0x40155d0 (index) redirected to 0x3802cf63 (vgPlain_x86_linux_REDIR_FOR_index) --5166-- Reading syms from /usr/lib/valgrind/x86-linux/vgpreload_core.so (0x401F000) --5166-- Reading syms from /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so (0x4022000) ==5166== WARNING: new redirection conflicts with existing -- ignoring it --5166-- new: 0x040155d0 (index ) R-> 0x040261a0 index --5166-- REDIR: 0x40157c0 (strlen) redirected to 0x4026450 (strlen) --5166-- Reading syms from /usr/lib/debug/libc-2.8.90.so (0x402A000) --5166-- REDIR: 0x409d2f0 (rindex) redirected to 0x4026080 (rindex) --5166-- REDIR: 0x409cf00 (strlen) redirected to 0x4026430 (strlen) --5166-- REDIR: 0x409d110 (strncmp) redirected to 0x40266a0 (strncmp) --5166-- REDIR: 0x409c7e0 (index) redirected to 0x4026170 (index) --5166-- REDIR: 0x409df70 (memset) redirected to 0x4027340 (memset) --5166-- REDIR: 0x4099c50 (calloc) redirected to 0x4023d20 (calloc) --5166-- REDIR: 0x409a190 (memalign) redirected to 0x4023b80 (memalign) --5166-- REDIR: 0x409e490 (memcpy) redirected to 0x40268a0 (memcpy) --5166-- REDIR: 0x409e180 (stpcpy) redirected to 0x40270d0 (stpcpy) --5166-- REDIR: 0x409dfd0 (mempcpy) redirected to 0x4027470 (mempcpy) --5166-- REDIR: 0x409f010 (strchrnul) redirected to 0x4027410 (strchrnul) VIDIOC_QBUF error 22, Invalid argument --5166-- REDIR: 0x4097730 (free) redirected to 0x4024a90 (free) ==5166== ==5166== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1) --5166-- --5166-- supp: 11 dl-hack3-cond-1 ==5166== malloc/free: in use at exit: 2,457,632 bytes in 5 blocks. ==5166== malloc/free: 5 allocs, 0 frees, 2,457,632 bytes allocated. ==5166== ==5166== searching for pointers to 5 not-freed blocks. ==5166== checked 51,772 bytes. ==5166== ==5166== 32 bytes in 1 blocks are still reachable in loss record 1 of 2 ==5166== at 0x4023DE2: calloc (vg_replace_malloc.c:397) ==5166== by 0x80494AF: init_userp (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== by 0x80498B0: init_device (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== ==5166== ==5166== 2,457,600 bytes in 4 blocks are still reachable in loss record 2 of 2 ==5166== at 0x4023C4A: memalign (vg_replace_malloc.c:460) ==5166== by 0x8049536: init_userp (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== by 0x80498B0: init_device (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== by 0x8049B63: main (in /home/juser/vga2usb/v4l.org/examples/capture) ==5166== ==5166== LEAK SUMMARY: ==5166== definitely lost: 0 bytes in 0 blocks. ==5166== possibly lost: 0 bytes in 0 blocks. ==5166== still reachable: 2,457,632 bytes in 5 blocks. ==5166== suppressed: 0 bytes in 0 blocks. --5166-- memcheck: sanity checks: 0 cheap, 1 expensive --5166-- memcheck: auxmaps: 0 auxmap entries (0k, 0M) in use --5166-- memcheck: auxmaps_L1: 0 searches, 0 cmps, ratio 0:10 --5166-- memcheck: auxmaps_L2: 0 searches, 0 nodes --5166-- memcheck: SMs: n_issued = 10 (160k, 0M) --5166-- memcheck: SMs: n_deissued = 0 (0k, 0M) --5166-- memcheck: SMs: max_noaccess = 65535 (1048560k, 1023M) --5166-- memcheck: SMs: max_undefined = 34 (544k, 0M) --5166-- memcheck: SMs: max_defined = 20 (320k, 0M) --5166-- memcheck: SMs: max_non_DSM = 10 (160k, 0M) --5166-- memcheck: max sec V bit nodes: 0 (0k, 0M) --5166-- memcheck: set_sec_vbits8 calls: 0 (new: 0, updates: 0) --5166-- memcheck: max shadow mem size: 464k, 0M --5166-- translate: fast SP updates identified: 1,933 ( 89.4%) --5166-- translate: generic_known SP updates identified: 128 ( 5.9%) --5166-- translate: generic_unknown SP updates identified: 100 ( 4.6%) --5166-- tt/tc: 4,312 tt lookups requiring 4,351 probes --5166-- tt/tc: 4,312 fast-cache updates, 3 flushes --5166-- transtab: new 2,035 (43,121 -> 617,673; ratio 143:10) [0 scs] --5166-- transtab: dumped 0 (0 -> ??) --5166-- transtab: discarded 8 (200 -> ??) --5166-- scheduler: 25,512 jumps (bb entries). --5166-- scheduler: 0/2,355 major/minor sched events. --5166-- sanity: 1 cheap, 1 expensive checks. --5166-- exectx: 769 lists, 8 contexts (avg 0 per list) --5166-- exectx: 16 searches, 8 full compares (500 per 1000) --5166-- exectx: 4 cmp2, 26 cmp4, 0 cmpAll --5166-- errormgr: 8 supplist searches, 271 comparisons during search --5166-- errormgr: 11 errlist searches, 26 comparisons during search
from v4l list Andy Walls:
It looks like init_userp() allocated a bunch of "buffers", which has to happen for a program to use user pointer mode of v4l2. The function errno_exit() doesn't bother to clean up when the VIDIOC_QBUF ioctl() call fails. free() is only called by uninit_device(). Since the alternate flow of the program through errno_exit() to termination doesn't call free() on "buffers", you should have a process heap memory leak on error exit.
program didn't close it's file descriptors with the driver on errno_exit()
capabilities mismatch
Looking at the source, capture.c should have reported "does not support user pointer" by:
411 init_userp (unsigned int buffer_size) 421 req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_USERPTR; 427 if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { fprintf (stderr, "%s does not support " "user pointer i/o\n", dev_name); exit (EXIT_FAILURE);
But instead it errors here:
250 start_capturing (void) 260 case IO_METHOD_USERPTR: if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) errno_exit ("VIDIOC_QBUF");