Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

sniper: bundled PipeWire 0.3.65 segfaults/deadlocks games on Bluetooth profile switch (fixed upstream in 1.2.2)

Abierto
#853 6 comentarios 0 reacciones 0 asignados Ver en GitHub

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

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

Need Retest

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:

  1. Host running a modern PipeWire (1.2.2+) and WirePlumber, with bluetooth.autoswitch-to-headset-profile at its default true.
  2. Pair a Bluetooth headset exposing both A2DP and HSP/HFP, and connect it.
  3. Launch CS2 (sniper runtime).
  4. Open Settings -> Audio and click the audio device selector dropdown.
  5. The game segfaults in libspa-audioconvert.so, or deadlocks with orphaned pw-data-loop threads.

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

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de ValveSoftware/steam-runtime

Todos los issues de ValveSoftware/steam-runtime

Issues similares

Más issues de Shell/Bash

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.