https://bugs.kde.org/show_bug.cgi?id=524408
Bug ID: 524408
Summary: Screencasting stays permanently broken ("Buffer
allocation failed") after a transient PipeWire
fd-exhaustion desyncs kwin's connection — cached
PipeWireCore is only invalidated on EPIPE
Classification: Plasma
Product: kwin
Version First 6.6.6
Reported In:
Platform: NixOS
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: screencasting
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
SUMMARY
After the PipeWire daemon briefly runs out of file descriptors while kwin has
screencast streams open, kwin's (cached, shared) PipeWire connection ends up
with a desynced fd/mem-id table. From then on EVERY new screencast on that
connection fails with "Buffer allocation failed" — OBS, browsers, the portal's
own "Share screen" dialog — until the user logs out or knows how to kick the
connection from a shell. Restarting the consumer app does not help; kwin is the
broken side. kwin recovers only if the daemon happens to close the connection
(EPIPE); a poisoned-but-connected core is kept forever.
The trigger (fd exhaustion) is arguably a PipeWire/config issue and I'll raise
it there separately, but the *stickiness* is kwin's:
src/plugins/screencast/pipewirecore.cpp PipeWireCore::onCoreError() only sets
m_valid = false for (id == PW_ID_CORE && res == -EPIPE), and
ScreencastManager::getPipewireConnection() reuses m_pipewireConnectionCache as
long as isValid(). Verified unchanged in current master.
ENVIRONMENT
- Plasma / kwin 6.6.6, Wayland session, NixOS
- PipeWire 1.6.6, WirePlumber 0.5.14, xdg-desktop-portal 1.20.4,
xdg-desktop-portal-kde 6.6.6
- pipewire.service: LimitNOFILE soft 1024 / hard 524288 (systemd default;
distro unit sets nothing)
- GPU: NVIDIA RTX 5090, open kernel module 595.71.05 (DMA-BUF modifier
0x300000000606014 negotiated); VRAM 6/32 GB used, no driver errors at failure
time
- Consumer: OBS Studio 32.1.2 with 14 PipeWire screencast sources across scenes
(all sessions are opened at OBS start)
TIMELINE (2026-08-18, session up since 08-11; full excerpt attached)
10:00:16 OBS starts -> 14 screencast sessions at once -> pipewire daemon hits
its 1024 fd soft limit:
pipewire: mod.protocol-native: connection 0x…: can't DUP fd:617 Too
many open files
pipewire: pw.mem: 0x…: Failed to create memfd: Too many open files
10:00:20 first desync errors, sent by kwin's client connection (client-side
libpipewire, src/pipewire/core.c core_event_add_mem):
pipewire: pw.core: 0x…: error -22 for resource 0: invalid mem id 105,
expected 41
pipewire: pw.core: 0x…: error -2 for resource N: set_activation: No
such file or directory
pipewire: pw.core: 0x…: error -2 for resource N: node_set_io failed:
No such file or directory
10:00:21 daemon drops kwin's connection -> kwin_wayland: PipeWire remote
error: connection error (EPIPE)
-> kwin creates a fresh PipeWireCore -> screencasts work again from
10:00:34, all morning.
13:44:13 OBS restarted (14 sessions) -> same fd exhaustion -> same desync
("invalid mem id 119, expected 110" ...)
13:45:07 OBS restarted again -> also "mod.client-node: can't create node: Too
many open files"
This time the daemon does NOT drop kwin's connection. From here on,
every stream created on it fails:
kwin_wayland: "DP-4" Stream error: Buffer allocation failed
kwin_wayland: PipeWire remote error: Buffer allocation failed
pipewire: pw.core: 0x…: error -2 for resource 36:
port_use_buffers(1:0:-1) error: No such file or directory <- direction 1 =
OUTPUT = kwin's source node
pipewire: pw.link: (246.0.0 -> 164.0.0) allocating -> error Buffer
allocation failed (-2) (paused-ready)
OBS: [pipewire] Stream 0x… state: "error" (error: Buffer allocation
failed) — for all 14 sources, across 3 OBS restarts (13:44, 13:45, 13:48)
13:58:49 workaround from a shell: `pw-cli destroy <kwin's client id>` ->
daemon closes kwin's connection
-> kwin_wayland: PipeWire remote error: connection error -> new
PipeWireCore
13:59:02 next screencast negotiates and streams normally. Nothing else was
restarted; kwin never crashed.
MECHANISM (as far as I can tell)
When the daemon can't dup() an fd for a message it still delivers the message;
on the receiving side (kwin's libpipewire) fd indexes/mem-ids no longer line
up. pw_mempool_import() then finds an existing memblock with the same fd number
(mempool_find_fd) and returns it with a different id -> "invalid mem id X,
expected Y" -> subsequent set_activation / port_use_buffers on that connection
fail with ENOENT -> pw_link reports "Buffer allocation failed". Same family as
pipewire#2914 (stale imported memblock / fd reuse), but here on the client side
and caused by the daemon's ENFILE.
WHY IT'S A KWIN BUG TOO
- PipeWireCore::onCoreError(): only EPIPE marks the core invalid. Any other
core error (here -EINVAL from add_mem, or repeated -ENOENT) leaves m_valid =
true.
- ScreencastManager::getPipewireConnection(): returns m_pipewireConnectionCache
while isValid() -> the poisoned connection is reused for every subsequent
stream, forever.
- Net effect for users: screen sharing "just stops working" for the rest of the
session with no hint; the fix they find online is "log out" or "restart
pipewire".
SUGGESTED FIX
Treat any PW_ID_CORE error (not only -EPIPE), or N consecutive fresh streams
failing during allocation, as "connection unusable": set m_valid = false, emit
pipewireFailed so existing streams tear down, and let the next stream create a
fresh PipeWireCore — the path MR !5708 already implements for EPIPE. Then a
transient daemon hiccup costs one failed attempt instead of the whole session.
POSSIBLE REPRODUCER (not tried here, offered as an idea)
Lower the running daemon's soft fd limit close to its current usage (e.g.
prlimit --pid $(pidof pipewire) --nofile=<usage+5>:524288), start a screencast
consumer that opens several sessions at once so the daemon hits ENFILE while
kwin's connection is alive, then restore the limit. If kwin logs the desync
errors above but no "connection error", every following screencast on that
session should fail until pw-cli destroy / logout.
WORKAROUND (verified)
pw-cli ls Client | grep -B2 kwin # find kwin's client id
pw-cli destroy <id> # kwin gets EPIPE, reconnects; next
screencast works
No audio interruption, no compositor restart.
ATTACHMENTS
- journal excerpt (kwin / pipewire daemon / xdg-desktop-portal-kde / OBS)
covering the four windows above, repeated lines collapsed with counts
- OBS log of the 13:48 start (all sources failing on the poisoned connection)
RELATED
- kwin MR !5708 "Reconnect Pipewire on Failure" (bug 483137) — introduced the
cached shared connection and the EPIPE-only invalidation
- pipewire#2914 — same stale-memblock/fd-reuse mechanism, fixed daemon-side in
2023
--
You are receiving this mail because:
You are watching all bug changes.