Genymobile / Genymobile/scrcpy
Unbounded device-side DMA-BUF growth when the desktop client stops consuming video
- Dominant language
- C
- Stars
- 150k
- Forks
- 13.7k
- Avg merge
- 4d 13h
- Merged PRs (30d)
- 2
Description
## 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
1. Display continuously changing content on the Android device. A webpage containing a CSS animation is sufficient.
2. Start scrcpy normally:
```console
scrcpy -s
```
3. Verify that screen mirroring is working.
4. 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.
5. Keep the ADB connection alive and monitor device-side DMA-BUF usage:
```console
adb -s shell dmabuf_dump
adb -s shell cat /sys/kernel/debug/dma_buf/bufinfo
```
6. Resume 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
```text
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:
```text
main:23525
PROCESS TOTAL 616148 kB
dmabuf total: 841920 kB
kernel_rss: 225772 kB
userspace_rss: 616148 kB
```
PID 23525 was confirmed to be:
```text
app_process / com.genymobile.scrcpy.Server 4.1
```
The DMA-BUF snapshot contained:
```text
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:
```text
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:
```text
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:
```text
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.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the scrcpy-server video packet write path and its MediaCodec/Codec2 interaction, then reproduce the issue with a suspended desktop client while monitoring device-side DMA-BUF usage. Done means a stalled connected client no longer allows unbounded DMA-BUF growth, with behavior verified by resuming the client or triggering the chosen defensive safeguard.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, c
- Domain
- mobile-dev, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100