Unbounded device-side DMA-BUF growth when the desktop client stops consuming video
Environment
- OS: Windows 11 x64, build 26200.9168
- scrcpy version: 4.1
- Installation method: official Windows release archive
- Also reproduced with: scrcpy 3.3.4 and 3.3.1
- Connection: USB ADB
- Device manufacturer: Shimeta
- Device model: 3576E
- SoC: Rockchip RK3576
- Android version: 14 / API 34
- Build fingerprint:
ShimetaOS/3576E/rk3576:14/UQ1A.240205.004.B1/eng.hwt.20260107.104755:userdebug/release-keys - Kernel: Linux 6.1.75, aarch64
Description
When the desktop scrcpy process stops consuming video data but remains alive and keeps the ADB/socket connection open, the device-side scrcpy-server accumulates DMA-BUF objects without an apparent upper bound.
With continuously changing screen content, DMA-BUF usage grows by approximately 120-170 MB/s until the desktop process resumes reading or the device-side server exits.
A simple CSS animation in a browser is sufficient to reproduce the issue. No video playback, video call, or hardware video decoder is required.
Normal scrcpy operation is stable. Normal exit or killing the desktop process usually closes the connection and releases the buffers. The problematic condition is a stalled but still-connected desktop client.
If allowed to continue, this can exhaust device memory and freeze the whole Android system. In controlled tests, I stopped the reproduction after DMA-BUF exceeded 3 GiB.
Steps to reproduce
Display continuously changing content on the Android device. A webpage containing a CSS animation is sufficient.
Start scrcpy normally:
scrcpy -s <serial>Verify that screen mirroring is working.
Suspend the desktop scrcpy process without terminating it or closing its handles.
On Windows, I reproduced this using
NtSuspendProcess. Suspending the process from Process Explorer should be equivalent.Keep the ADB connection alive and monitor device-side DMA-BUF usage:
adb -s <serial> shell dmabuf_dump adb -s <serial> shell cat /sys/kernel/debug/dma_buf/bufinfoResume the desktop scrcpy process before the device runs out of memory.
A static screen did not cause noticeable growth during a 30-second test. Continuously changing screen content fills the transport buffers quickly and makes the issue reproducible within seconds.
Results with scrcpy 4.1
11:51:37 DMA-BUF=246,240 kB
11:51:39 DMA-BUF=246,240 kB
11:51:42 DMA-BUF=246,240 kB
11:51:44 DMA-BUF=382,920 kB
11:51:45 DMA-BUF=529,800 kB
11:51:46 DMA-BUF=686,880 kB
11:51:47 DMA-BUF=841,920 kB
At the last sample:
main:23525
PROCESS TOTAL 616148 kB
dmabuf total: 841920 kB
kernel_rss: 225772 kB
userspace_rss: 616148 kB
PID 23525 was confirmed to be:
app_process / com.genymobile.scrcpy.Server 4.1
The DMA-BUF snapshot contained:
303 objects of 2,088,960 bytes
exporter: system
name: system
These objects accounted for approximately 633 MB.
The hardware-related buffer counts did not grow with the leak:
rkvdec: 0 objects, 0 bytes
rkvenc: 8 objects, 33,841,152 bytes
After resuming the desktop process, DMA-BUF usage quickly dropped to approximately 293 MB and remained stable.
Longer reproduction with scrcpy 3.3.4
The same test was allowed to continue until DMA-BUF exceeded 3 GiB:
11:23:45 246,240 kB
11:23:55 962,280 kB
11:24:00 1,588,560 kB
11:24:05 2,237,280 kB
11:24:10 2,906,400 kB
11:24:13 3,259,320 kB
At the peak:
com.genymobile.scrcpy.Server process total: 3,031,532 kB
2,088,960-byte system DMA-BUF objects: 1,489
Resuming the desktop process released the accumulated buffers.
Expected behavior
If the desktop client stops reading while the connection remains open, device-side resource usage should remain bounded.
Acceptable behavior could be any of the following:
- the encoder blocks after a bounded number of outstanding buffers;
- frames are dropped;
- the connection is closed after a write/no-progress timeout;
- the encoder or server is stopped after the output remains blocked for too long.
The condition should not allocate DMA-BUF indefinitely until Android becomes unresponsive.
Analysis and defensive mitigation request
I understand that the primary defect is probably in the device ROM's MediaCodec/Codec2 encoder backend. A codec implementation should apply bounded backpressure when output buffers are not released instead of allocating an unlimited number of DMA-BUF objects.
However, a stalled-but-still-open transport can occur in practice, for example when the desktop process hangs or when an ADB connection becomes half-open. On a ROM with this encoder defect, the current behavior can freeze the entire device.
Would it be possible for scrcpy-server to add a defensive safeguard, such as:
- a bounded/no-progress timeout around video packet writes;
- stopping or resetting the encoder if no packet can be delivered for a configured period;
- terminating the server when the desktop peer remains connected but does not consume data.
This would not replace a firmware fix, but it would prevent defective MediaCodec implementations from exhausting all device memory.
Possibly related issues
- #3563
- #6271
- #4297
- #6411
Full dmabuf_dump, bufinfo, and timestamped DMA-BUF samples can be provided if useful.
Source: Genymobile/scrcpy