RtAudio ALSA apps on pipewire-alsa, calling snd_pcm_drain and snd_pcm_prepare, hang in poll()
If you are filing this issue with a regular release please try master as it might already be fixed.
Version, Distribution, Desktop Environment:
- pipewire-git/pipewire-alsa-git 0.3.32.43.g44583367-1, commit 44583367 (current master)
- Arch Linux
- KDE Plasma X11
Description of Problem:
When testing RtAudio apps running under
pipewire-alsa, I found that when BambooTracker was set to use ALSA (the
default device aliasing to
pipewire), the audio thread would hang after I opened a document.
Steps to Reproduce:
- Install pipewire[-git] and pipewire-alsa[-git] on a system, and uninstall pulseaudio-alsa if present. Start the pipewire daemon.
- On Arch, the pipewire-alsa[-git] package will produce "/etc/alsa/conf.d/99-pipewire-default.conf" which sets the
defaultALSA device to point to
pipewire. If not present on your distro, copy/link it somehow.
- Clone BambooTracker git master from https://github.com/BambooTracker/BambooTracker, and build and run it. (On Arch, you can install aur/bambootracker-git.)
- There are prebuilt binaries at https://github.com/BambooTracker/BambooTracker/releases/download/v0.4.6/BambooTracker-v0.4.6-linux.zip, but it's 124 megabytes and is some strange nix-os shell script thing.
- In File -> Configuration -> Sound, by default the API should be set to ALSA and Device to default. If not, set it that way. Then click OK to close the Configuration dialog.
- Press the "New" toolbar icon. The audio thread is now locked up.
- To hang the app UI (due to mutex contention), press the "New" icon a second time.
Audio thread hangs when loading a new file.
Audio thread continues working when loading a new file. This issue does not occur with pulseaudio-alsa (along with either pulseaudio or pipewire-pulse).
Additional Info Eg.
pw-dump -N > file (As Attachment Please):
pwdump (pw-dump output doesn't change between before/after the audio thread hangs, aside from pw-dump itself being a different process.)
Through breakpoints, debug logs, and ltrace, I traced this down to BambooTracker's UI thread calling:
This is followed by both function calls again. (The program is janky.) However, the hang still occurs if I modify the program to only call each method once, by commenting out "BambooTracker/gui/mainwindow.cpp"
MainWindow::assignADPCMSamples()'s function body.
Meanwhile, the audio thread is repeatedly calling:
snd_pcm_writeiamong other functions
The first few calls to
RtApiAlsa::callbackEvent() would succeed, but then
snd_pcm_writei would hang in a
#0 0x00007ffff66a0b2f in poll () from /usr/lib/libc.so.6 #1 0x00007ffff7e9d7de in snd1_pcm_wait_nocheck () from /usr/lib/libasound.so.2 #2 0x00007ffff7ea1842 in snd1_pcm_write_areas () from /usr/lib/libasound.so.2 #3 0x00007ffff7eabf3f in snd_pcm_mmap_writei () from /usr/lib/libasound.so.2 #4 0x00007ffff7ee34e2 in snd_pcm_ioplug_writei () from /usr/lib/libasound.so.2 #5 0x00005555557e9c36 in RtApiAlsa::callbackEvent() () #6 0x00005555557ea46f in alsaCallbackHandler(void*) () #7 0x00007ffff6af7259 in start_thread () from /usr/lib/libpthread.so.0 #8 0x00007ffff66ab5e3 in clone () from /usr/lib/libc.so.6
(I read that ALSA functions operating on handles are not thread-safe unless synchronized with mutexes. From my reading of the code, I think
RtApiAlsa::callbackEvent() all properly acquire mutexes while calling
snd_pcm_* functions, so I think it's following the ALSA contract.)
If I run
PIPEWIRE_DEBUG=4 BambooTracker, after the hang occurs, I see nonstop:
[D][13340.529630][ pcm_pipewire.c: 377 on_stream_drained()] alsa-plugin 0x556530a08170: drained
pipewire-debug I ran a trace of
PIPEWIRE_DEBUG=4 BambooTracker. (Higher levels would generate spam logs nonstop even before the hang occurred.) I think the relevant events are emitted by
pcm_pipewire.c, starting at
pipewire-alsa is mismanaging its buffers such that calling
snd_pcm_writei to stop draining.
I found a similar but not identical issue from 2010, caused by
snd_pcm_pause rather than
snd_pcm_drain: [alsa-devel] Hang in snd_pcm_writei with alsa-pulse plugin