unicam/vc4 (BCM2711): every camera configure+allocate cycle leaks its dma-bufs — CMA exhausted in ~10 capture cycles
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 38/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- c, linux
- 领域
- backend, embedded-iot
调研方向
Start by tracing the unicam/bcm2835-isp capture path and its dma-buf import and release handling, especially the vcsm-cma and bcm2835-isp paths mentioned in the report. Compare their cleanup behavior with the earlier fixes raspberrypi/linux#3220, #3946, #4277, and #4599. Reproduce by rebuilding buffers repeatedly on the Pi Zero 2 W; done means each cycle’s dma-bufs are released and CMA use stays flat.
由索引模型根据 Issue 内容生成。
描述
Describe the bug
Disclosure: this report was drafted by an AI coding assistant (opencode,
GLM) working with a human engineer who owns the hardware and reviewed the
measurements. The bench tooling was written by the assistant; all
experiments were run on the engineer's Raspberry Pi Zero 2 W test boards.
In short: whenever a program has the camera throw away its picture
buffers and make new ones, the kernel permanently loses the old ones —
about 19 MB per change at the largest picture size.
On the BCM2711 unicam/bcm2835-isp capture path (rpi/vc4 pipeline), every
cycle that frees and reallocates a libcamera camera's stream buffers
leaks that whole set into kernel-held dma-bufs — a full build/teardown
(configure+allocate+start/stop+release) AND an in-place reconfigure on
the same acquired camera (configure+allocate alone, no release/acquire)
leak at the same per-cycle rate, on both sensors we tried (imx219,
imx708). A USB (UVC) camera on the same board does not leak: the bug is
specific to the vc04 capture path, not to camera-buffer handling in
general. A long-running process (one buffer-set rebuild per quality-rung
change) exhausts the 256 MB CMA reserve in about ten 1440x1080 cycles;
allocation then fails for every subsequent camera start until the
process exits (or the board reboots). In one real day-long process the
table grew to 1,412 objects / 187.8 MB, the leaked sizes matching the
application's three configured stream sizes verbatim (622,592 / 970,752
/ 2,387,968 B per buffer).
What the kernel still holds after one full rebuild of the camera
(bufferCount 8, YUV420 1440x1080, 2,387,968 B per buffer):
- +8
videobuf2_dma_contigdma-bufs (19,103,744 B) remain in
/sys/kernel/debug/dma_buf/bufinfo after a full teardown
(camera->stop(), requests cleared, allocator freed, munmap,
camera->release(), manager left running). - Each leaked object shows count 00000002 (file f_count) with no
userspace fds and "Total 0 devices attached". lsmoduse-count of videobuf2_dma_contig climbs ~8 per cycle (34
mid-run vs 3 idle on an otherwise quiet board).- The process's own fd table is clean (no leaked device or dma-buf fds);
process exit drains the whole table at once — nothing is held by the
loaded modules once the client is gone. - /sys/kernel/debug/vcsm-cma/state shows a live VPU-held import of a
videobuf2_dma_contig buffer mid-run (SIZE 2564096).
Steps to reproduce the behaviour
Step 1: see how much camera memory the kernel holds right now, so there
is a starting number to compare against. On a Pi Zero 2 W with a MIPI
camera (imx219 or imx708) on the rpi/vc4 pipeline:
sudo grep -c videobuf2_dma_contig /sys/kernel/debug/dma_buf/bufinfo
Step 2: make the camera throw away its picture buffers and rebuild them,
over and over, inside one single program — that is the action that loses
the memory on the affected boards. All cycles must live in ONE process:
the leak only piles up within a program (a program exit hands everything
back, so one process per run). Per cycle, with the plain libcamera API:
- generateConfiguration(StreamRole::VideoRecording); set the stream to
1440x1080, bufferCount 8, YUV420; validate; camera->configure(). - FrameBufferAllocator::allocate(stream) — one fresh buffer set.
- one Request per buffer (addBuffer), camera->start(), queue all
requests, deliver ~2 s (requeue each completed request with
Request::ReuseBuffers), camera->stop(). - free the whole set: clear the requests, allocator->free(stream).
No camera release/acquire is needed between cycles (that path was benched
separately; it leaks at the same rate). No other dependencies beyond
libcamera itself.
Step 3: compare against the starting number — every cycle should have
left one full set of picture buffers behind, and after about ten cycles
the camera memory pool is used up, so no camera can start until the
program exits. On a leaking kernel (6.18.50+rpt-rpi-v8 tested): +8
videobuf2_dma_contig objects / +19,103,744 B per cycle at 1440x1080
(bufferCount 8, 2,387,968 B per buffer); the objects remain after each
cycle's teardown and only drain at client process exit.
To show the trigger is exactly "buffers thrown away and remade" — and
nothing nearby — the same board was measured with (all benched): the
same stream stop/start on ONE configured camera with the buffers held
leaks nothing (+0 B per cycle); a USB (UVC) camera on the same board
leaks nothing; picture-size changes are irrelevant (re-making the same
size leaks identically).
Device (s)
Raspberry Pi Zero 2 W
System
The software the leak was found and measured on:
$ cat /etc/rpi-issue
Raspberry Pi reference 2026-09-15
$ vcgencmd version
Sep 14 2026 14:50:41
Copyright (c) 2012 Broadcom
version a86983925695a7e63166327d7c002d64040ed31d (clean) (release) (start)
$ uname -a
Linux racer0 6.18.50+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.18.50-1+rpt1 (2026-09-11) aarch64 GNU/Linux
libcamera 0.7.2+rpt20261009-1 (Debian package; identical on both test boards).
Logs
The measured proof, one line per rebuild: every cycle adds one full set
of picture buffers, until the camera memory pool runs out at cycle 8
(imx708 board, 20-cycle run):
cycle 1/20: 50 frames, 2746 ms, fds 4; dma-buf 8 objs 19103744 B total (vb2 8 objs 19103744 B) — delta +8 objs +19103744 B vb2
cycle 2/20: 50 frames, 2442 ms, fds 4; dma-buf 16 objs 38207488 B total (vb2 16 objs 38207488 B) — delta +8 objs +19103744 B vb2
cycle 3/20: 50 frames, 2531 ms, fds 4; dma-buf 24 objs 57311232 B total (vb2 24 objs 57311232 B) — delta +8 objs +19103744 B vb2
cycle 8/20: INIT FAILED: libcamera: buffer allocation failed
cycles: table over the run: 56 objs 133726208 B total (vb2 56 objs 133726208 B); grown from start +56 objs +133726208 B vb2
The same cycles on a USB (UVC) camera, same board: delta +0 objs +0 B
every cycle; the table drains to 0 at client exit.
Additional context
Everything we tried, so the search starts narrow (20 cycles x 2 s per
leg unless noted):
- Clean rebuild cycle (init -> allocate -> start -> stop -> free ->
release): leaks exactly one buffer set per cycle. - Same cycle with the zero-copy encoder, with a copy-encoder wrapper,
or capture-only without any encoder: identical leak —
encoder-independent. - In-place reconfigure, same acquired camera, NO release/acquire
(stop -> configure -> allocate -> start per cycle): leaks +8 objects
per cycle — device reopen is not part of the trigger. - Readout pin alternated at fixed dims: leaks identically at both
readouts. - Same-size control, reconfigure+reallocate at UNCHANGED dims: leaks
exactly 19,103,744 B per cycle — dims changes are irrelevant. - Second sensor, second board (imx708 wide NoIR on another Pi Zero 2 W):
leaks identically — +8 objects / 19,103,744 B per rebuild cycle; CMA
exhausted at cycle 8 (133,726,208 B held) and the failed allocate
leaked nothing extra. Sensor-independent. - Stream stop/start on ONE configured camera, same buffers held: FLAT,
+0 B per cycle — only freed-and-reallocated buffer sets leak, whatever
the acquisition history. - One shared CameraManager across cycles: still +1 set per cycle —
manager churn exonerated. - A failed allocate with CMA exhausted: leaks nothing extra.
- Process exit: drains the whole table to 0.
- USB (UVC) camera on the SAME Pi Zero 2 W (same kernel, libcamera and
CMA reserve; only the capture path changed): FLAT, +0 objects / +0 B
over 20 rebuild cycles — the leak is confined to the
unicam/bcm2835-isp (vc04) capture path, not a general camera-buffer
behavior. - USB (UVC) capture on a Pi 5 (BCM2712, different SoC and pipeline):
FLAT, +0 objects / +0 B over 20 rebuild cycles.
This bug family has been seen and fixed before: raspberrypi/linux#3220
("unicam: CMA Memory leak", 2019) — same signature (module use-count +8
per cycle, dma-bufs left in bufinfo, CMA drain per qcam launch); root
cause then was a
dma_buf_get/dma_buf_put imbalance on re-presented buffers (fixed by
PR #3293 in bcm2835-codec). The present leak's flat f_count=2 (not
per-presentation) and its survival of manager reuse suggest the imbalance
moved or reappeared elsewhere in the vc04 import path (bcm2835-isp /
vcsm-cma import side). Earlier merged fixes in the same import/CMA path:
#3946/#4277 (vcsm-cma: missing dmabuf detach on import, 2020/2021) and
#4599 (codec streamoff CMA leak, 2021) — this path has leaked before,
from more than one cause.
Ask: point us at a fix if one exists; otherwise we hope the recipe makes
the bisection cheap.
- 主要语言
- C
- 星标
- 13.3k
- 派生
- 5.5k
- 平均合并
- 3 天 20 小时
- 30 天内合并 PR
- 27
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
raspberrypi/linux 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 63/100
raspberrypi/linux#7718 · 2 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
raspberrypi/linux#7415 · 2 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
rp1-cfe doesn't forward V4L2_EVENT_SOURCE_CHANGE event from csi-2 sensor driver to userspace app未关闭
难度 2/5 1-3 小时 新手友好度 72/100
raspberrypi/linux#7399 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 82/100
raspberrypi/linux#7357 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
raspberrypi/linux#7054 · 2 条评论 ·
维护者通常 1 天内回复
查看 raspberrypi/linux 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 85/100
维护者通常 1 天内回复
-
SPIDevice selects an active-high device as soon as it is created可能已有人在做 @mikeysklar 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 73/100
adafruit/circuitpython#11869 ·
维护者通常 1 天内回复
-
难度 1/5 1 小时以内 新手友好度 78/100
gnif/LookingGlass#1352 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 72/100
kovidgoyal/kitty#10862 ·
维护者通常 1 天内回复