sniper: bundled PipeWire 0.3.65 segfaults/deadlocks games on Bluetooth profile switch (fixed upstream in 1.2.2)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 55/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- audio-video-rtc
Línea de trabajo
Comienza con la política de backporting del README de steamrt y las versiones de los paquetes incluidos en sniper_platform_3.0.20260805.254768/files/manifest.dpkg. Revisa las correcciones de PipeWire 628f292fb877440f9531cc452f81b59ac3471637 y 0d7c20760e56fc60db13f7d972baed4bc0760767 y, a continuación, sigue el proceso de actualización de paquetes del runtime. Se considera terminado cuando el PipeWire incluido contiene la corrección de 1.2.2, conserva el SONAME estable y la reproducción del cambio de perfil de Bluetooth ya no provoca crashes ni deadlocks.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
The sniper runtime bundles pipewire 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1 (upstream 0.3.65, released 2023-01-24). That version contains a known data race on SPA_IO_Buffers between the main thread and the pw-data-loop RT thread during port/format renegotiation, fixed upstream in PipeWire 1.2.2 (2024-07-29).
On a host with a modern PipeWire daemon, a Bluetooth headset switching profile (A2DP 48 kHz stereo <-> HSP/HFP 16 kHz mono) forces a mid-stream format renegotiation. The bundled 0.3.65 client then either SIGSEGVs in libspa-audioconvert.so or deadlocks the game.
In CS2 this reproduces on demand: with the headset connected, open Settings -> Audio and click the audio device selector dropdown. Enumerating devices re-creates the streams and drives the renegotiation straight into the racy window.
Observed with Counter-Strike 2, but this is a runtime-level defect and should affect any sniper game using audio with a Bluetooth headset.
Environment
| Component | Version |
|---|---|
| OS | Fedora 44 |
| Kernel | 7.1.8-200.fc44.x86_64 |
| CPU / GPU | Ryzen 9 5900X / Radeon RX 6700 XT (Mesa 26.1.7) |
| Host PipeWire | 1.6.8 |
| Host WirePlumber | 0.5.14 |
| Host BlueZ | 5.87 |
| sniper | 3.0.20260805.254768, pressure-vessel 0.20260805.0 |
| Bundled PipeWire | 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1 |
From sniper_platform_3.0.20260805.254768/files/manifest.dpkg:
libpipewire-0.3-0:amd64 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1
libpipewire-0.3-modules:amd64 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1
libspa-0.2-modules:amd64 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1
pipewire-bin 0.3.65-3+deb12u1~steamrt3.3+bsrt3.1
The host daemon flags the client as outdated on every stream creation:
pipewire[2300]: mod.client-node: detected old client version 4
Failure mode 1: SIGSEGV in libspa-audioconvert
kernel: pw-data-loop[1044288]: segfault at 21 ip 00007fdd599bba71 sp 00007fdd2c3fa270 \
error 4 in libspa-audioconvert.so[31a71,7fdd5999a000+3f000]
systemd-coredump: Process 1044176 (cs2) of user 1000 dumped core.
#0 0x00007fdd599bba71 n/a (/usr/lib/x86_64-linux-gnu/spa-0.2/audioconvert/libspa-audioconvert.so + 0x31a71)
Note the path /usr/lib/x86_64-linux-gnu/...: inside the pressure-vessel container, i.e. the runtime's bundled SPA plugin, not the host's /usr/lib64/.
objdump -d of the bundled libspa-audioconvert.so at the faulting offset:
31a54: cmp %r15d,0x463c(%r12) ; loop bound (port->blocks)
31a5e: mov 0x18(%r14),%rsi
31a65: lea (%rax,%rax,4),%rdx ; i * 5
31a69: mov 0x10(%rsi),%rax ; -> datas array base
31a6d: lea (%rax,%rdx,8),%rbx ; &datas[i], stride 40 == sizeof(struct spa_data)
31a71: mov 0x20(%rbx),%rax ; <-- FAULTS reading spa_data.chunk
31a75: movl $0x0,(%rax) ; chunk->offset = 0
31a7f: movl $0x0,0x4(%rax) ; chunk->size = 0
This is impl_node_process() in spa/plugins/audioconvert/audioconvert.c:
for (j = 0; j < port->blocks; j++) {
bd = &buf->buf->datas[j];
bd->chunk->offset = 0;
bd->chunk->size = 0;
Fault address 0x21 with error 4 (userspace read of an unmapped page): the datas array base resolved to 1, i.e. a stale/freed buffer touched during renegotiation.
Failure mode 2: deadlock (same trigger)
On a subsequent launch the game hangs instead of crashing:
1044793 cs2 [S] futex_do_wait
1044924 pw-data-loop [S] ep_poll
1044926 pw-data-loop [S] ep_poll
1044930 pw-data-loop [S] ep_poll
Three pw-data-loop threads in a single client, consistent with repeated stream re-creation without teardown. Server side:
pipewire-pulse: mod.protocol-pulse: [] timeout on stream ... channel:0
... channels 0-7 all time out
This also wedges the host audio graph: host-side wpctl status hangs, and the desktop volume applet shows two simultaneously-selected default sinks until wireplumber/pipewire are restarted.
Trigger evidence
kernel: Bluetooth: hci0: SCO packet for unknown connection handle 257
bluetoothd: btd_service_connect() a2dp-source profile connect failed for XX:XX:XX:XX:XX:XX: Device or resource busy
wireplumber: <WpSiStandardLink> link failed: item deactivated before format was set
At crash time the card was stuck in the voice profile, with A2DP not offered at all:
Active Profile: headset-head-unit
off : Off
headset-head-unit-cvsd : Headset Head Unit (HSP/HFP, codec CVSD)
headset-head-unit : Headset Head Unit (HSP/HFP, codec MSBC)
Upstream fix
Upstream issue: https://gitlab.freedesktop.org/pipewire/pipewire/-/work_items/4094 (closed 2024-08-01). Different surface trigger (EasyEffects creating a new output stream), same underlying race.
The defect is not a missing null check at the crash site. It is a race on port->io / SPA_IO_Buffers between the main thread performing format renegotiation and the RT data loop running impl_node_process(). Fix commits, all dated 2024-07-29:
| Commit | First release | Subject |
|---|---|---|
628f292fb877440f9531cc452f81b59ac3471637 |
1.2.2 | audioconvert: set IO_Buffers only when buffers are negotiated |
0d7c20760e56fc60db13f7d972baed4bc0760767 |
1.2.2 | impl-port: improve IO_Buffers management on ports |
61dcd8dedec3c56375e333113156ec7fbd0cd372 |
1.3.81 / 1.4.0 | audioconvert: set IO_Buffers only when buffers are negotiated (mainline) |
The fix routes port->io assignment through the RT data loop, and clears SPA_IO_Buffers on SPA_PARAM_Format change before the port leaves the data-thread schedule, closing exactly the window an A2DP <-> HFP switch hits.
Verified by ancestry check against the upstream repo:
$ git merge-base --is-ancestor 628f292fb 0.3.65 # -> false (0.3.65 predates the fix)
$ git merge-base --is-ancestor 61dcd8ded 1.6.8 # -> true
0.3.65 is dated 2023-01-24, roughly 18 months before the fix landed.
Steps to reproduce
Deterministic path, via CS2's in-game device enumeration:
- Host running a modern PipeWire (1.2.2+) and WirePlumber, with
bluetooth.autoswitch-to-headset-profileat its defaulttrue. - Pair a Bluetooth headset exposing both A2DP and HSP/HFP, and connect it.
- Launch CS2 (sniper runtime).
- Open Settings -> Audio and click the audio device selector dropdown.
- The game segfaults in
libspa-audioconvert.so, or deadlocks with orphanedpw-data-loopthreads.
Opening that dropdown makes the game enumerate and open the available audio devices, which tears down and re-creates streams and drives the port/format renegotiation into the racy window. This is consistent with the three orphaned pw-data-loop threads observed in failure mode 2: repeated stream re-creation without teardown.
The same crash also occurs without touching the menu, whenever the headset microphone is acquired and the profile autoswitches A2DP -> HSP/HFP mid-stream. The dropdown is simply the reliable way to trigger it on demand.
Workaround
Prevent the renegotiation entirely by disabling profile autoswitching on the host:
wpctl settings --save bluetooth.autoswitch-to-headset-profile false
Then reconnect the headset so it returns to a2dp-sink. This costs the headset microphone, since HFP is what was disabled, so it is not viable for players who need headset voice chat.
Request
Backport a current PipeWire into sniper. The steamrt README's backporting policy already names PipeWire as suitable for this (stable SONAME libpipewire-0.3.so.0), and recent sniper releases have carried updates for SDL, Vulkan-Loader, nss and others while PipeWire has stayed at the 0.3.65 baseline.
Possibly related, never root-caused: https://github.com/ValveSoftware/csgo-osx-linux/issues/3349 ("Game Freeze when bluetooth headset is connected", closed 2023), which matches failure mode 2 and was closed after the reporter removed PipeWire entirely.
- Lenguaje dominante
- Shell
- Estrellas
- 1.5k
- Forks
- 97
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de ValveSoftware/steam-runtime
-
Dificultad 4/5 3-5 días Aptitud para principiantes 58/100
ValveSoftware/steam-runtime#857 · 3 comentarios ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 52/100
ValveSoftware/steam-runtime#856 · 6 comentarios ·
-
Regression in latest SLR betas and steamrt3c Steam Client if using pam_tmpdir or pam_mktempPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 40/100
ValveSoftware/steam-runtime#855 · 4 comentarios ·
-
Need Retest Pressure Vessel
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
ValveSoftware/steam-runtime#854 · 4 comentarios ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
ValveSoftware/steam-runtime#851 · 3 comentarios ·
Todos los issues de ValveSoftware/steam-runtime
Issues similares
-
status:needs-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
alunduil/alunduil-chezmoi#874 ·
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
alunduil/zellij-claude-pair#53 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
FluidNumerics/fluid-walk-blocker#201 ·
Los mantenedores suelen responder en 1 día
-
cao-evolution cao-evolution:compiler-security
Dificultad 1/5 1-3 horas Aptitud para principiantes 72/100
githubnext/gh-aw-cao#16895 ·
Los mantenedores suelen responder en 1 día