ALSA device accessibility handling is racy -> devices disappear after tty switch
- PipeWire version (
pipewire --version
):
Compiled with libpipewire 0.3.54
Linked with libpipewire 0.3.54
- Distribution and distribution version (
PRETTY_NAME
from/etc/os-release
): openSUSE Tumbleweed - Desktop Environment: KDE Plasma
- Kernel version (
uname -r
): 5.18.9-2-default
Description of Problem:
After switching to a TTY and back, pipewire shows no active devices anymore.
How Reproducible:
This happens randomly, sometimes only a few times a day, sometimes almost every time.
Steps to Reproduce:
Switch from the desktop session to a TTY and then back. The audio icon is now crossed out and complains about missing devices.
Analysis
When switching active sessions, logind adds and removes "uaccess" acls for sound device access. pipewire listens to inotify ATTRIB events on /dev/snd/* and checks for accessibility there. The order of those ATTRIB changes appears to be random, e.g.:
/dev/snd/ ATTRIB controlC0
/dev/snd/ ATTRIB hwC0D0
/dev/snd/ ATTRIB pcmC0D0c
/dev/snd/ ATTRIB pcmC0D0p
/dev/snd/ ATTRIB seq
/dev/snd/ ATTRIB timer
or
/dev/snd/ ATTRIB pcmC0D0p
/dev/snd/ ATTRIB seq
/dev/snd/ ATTRIB controlC0
/dev/snd/ ATTRIB timer
/dev/snd/ ATTRIB hwC0D0
/dev/snd/ ATTRIB pcmC0D0c
(output from inotifywait -mr /dev/snd -e ATTRIB
)
Specifically, if /dev/snd/controlC0 is made accessible before the others, it breaks. If it made accessible last, it works.
This can be reproduced manually by assuming the role of logind and setting acls manually:
# Break access -> audio disabled
setfacl -m user:linux:- /dev/snd/*
# Grant access in the working order -> audio works again
setfacl -m user:linux:rw- /dev/snd/{pcm,hw,seq,timer}*; sleep 1; setfacl -m user:linux:rw- /dev/snd/controlC0
# Break access again -> audio disabled
setfacl -m user:linux:- /dev/snd/*
# Grant access in the broken order -> audio still broken!
setfacl -m user:linux:rw- /dev/snd/controlC0; sleep 1; setfacl -m user:linux:rw- /dev/snd/*
My hypothesis is that when pipewire notices that /dev/snd/controlC0
is accessible, it tries to open /dev/snd/pcmC0D...
as well, which fails if the ACL wasn't assigned yet. If so, check_access
would have to check accessibility of the PCM devices as well.