My .xinitrc runs gentoo-pipewire-launcher at system start but wireplumber fails to connect to pipewire printing "Failed to connect to PipeWire" and stoping. It seems wireplumber can be executed before pipewire is ready because of the way the script is coded. gentoo-pipewire-launcher: #!/bin/sh /usr/bin/pipewire & /usr/bin/pipewire -c pipewire-pulse.conf & exec /usr/bin/wireplumber A simple fix is putting a 'wait' command before starting wireplumber to be sure that pipewire has fully started. Reproducible: Always
I can confirm this. Adding sleep 2 after launching the pipewire core daemon helps, otherwise everything trying to start playback hard-locks.
Actually not true. I still had my pre-0.3.39 configuration in /etc/pipewire. After commenting out the context.exec entries in /etc/pipewire/pipewire.conf, everything seems to work fine, or I have been lucky on the second attempt.
Could the original filer please report back, too (regarding having stale configuration)? In my limited testing I did not observe any issues when not using any delay between daemon startup, which is why it's not there right now.
I don't have a '/etc/pipewire/' directory. Small_Penguin: If I try 'gentoo-pipewire-launcher' a second time after the failed attempt on system startup, it works, but it could be because the binaries are already cached so they run almost instantly. I've checked the systemd unit file of wireplumber and it has both "After=pipewire.service" and "BindsTo=pipewire.service", these directives, specially 'After=', instruct wireplumber to run only after pipewire service is fully started. That guarantee is not in 'gentoo-pipewire-launcher'. I recommend to run the three commands straight without '&', the second command 'pipewire -c pipewire-pulse.conf' does wait for 'pipewire' though, but it seems there is some polling time, so in fact running it in parallel could be slower.
There is no such thing as guaranteed daemon startup order without systemd (especially for user services), therefore I'm not aware of any way to implement After= condition for OpenRC. ;) My understanding is that pipewire -c pipewire-pulse.conf (a.k.a. pipewire-pulse) has long been fixed to reliably deal with getting started before the main pipewire -c pipewire.conf process, so startup order should not be a problem. I'm not sure how well WirePlumber can deal with getting initialized before PipeWire. Regarding not using & from what I knew both then and now the daemons remain running in the foreground, so once pipewire starts, it will not move on to starting the 2nd daemon until the first has exited. We could add a delay before starting WirePlumber but if it's only affecting one person, I'm a bit unsure if using a large value would be a good idea, and I doubt that just 1 second sleep will be reliable enough (and has it even been verified to help?). It may be worth to do `ps aux | grep -Ei wire\|pulse` before and after running the the launcher to see in what state is the system before and after running it Another thing to explore would be adding, say, sleep 1 after the pkill command since if there's already running daemons, they may not have managed to exit before pipewire & attempts to initialize. On that note, what software is being started via .xinitrc? Might it be an XDG compliant desktop environment such as Xfce4 which would try to run the launcher a second time thanks to the XDG autostart?
Forgot to tag bug (sorry, I'd planned on), but this is fixed in 0.3.40 / 9999 with a sleep 1 as a hack for now.
I worked around it by copying the default pipewire.conf to ~/ and replacing/uncommenting mentions of pw-media-session with wireplumber. None of these workarounds are all that great though; I think it's on upstream to ship a default config and set of daemons that isn't broken out of the box.
Niklāvs Koļesņikovs: > Regarding not using & from what I knew both then and now the daemons remain > running in the foreground, so once pipewire starts, it will not move on to > starting the 2nd daemon until the first has exited. Oh yeah I forgot that when writting. > We could add a delay before starting WirePlumber but if it's only affecting one > person I suppose very few people are testing pipewire plus 'gentoo-pipewire-launcher' script. > I'm a bit unsure if using a large value would be a good idea, and I doubt that just 1 > second sleep will be reliable enough (and has it even been verified to help?). It helps. But ideally wireplumber should implement this, I saw you in its GitLab repo maybe a feature request could pay off. > On that note, what software is being started via .xinitrc? Might it be an XDG > compliant desktop environment such as Xfce4 which would try to run the launcher > a second time thanks to the XDG autostart? I'm using AwesomeWM so no XDG autostart files. Sam James: > Forgot to tag bug (sorry, I'd planned on), but this is fixed in 0.3.40 / 9999 > with a sleep 1 as a hack for now. Ugly but it works. Thanks. Enne Eziarc: > I worked around it by copying the default pipewire.conf to ~/ and > replacing/uncommenting mentions of pw-media-session with wireplumber. That seems the most elegant solution.
There's three reasons we moved away from using the pipewire.conf method: 1. it's deprecated by upstream and meant only for the purpose of running tests and other specialized deployments 2. unlike some other custom patches we apply, that one had proven itself to require above average amount of maintenance, since it's at the end of the main configuration file and recurrently becomes unrecognizable to patch utility 3. no one really likes conditional patching in ebuilds (since it should not be applied to systemd user systems). Regarding WirePlumber, the primary use case of systemd works reliably (ignoring the previously hidden Gentoo issues that WirePlumber uncovered in other components), so I doubt non-systemd is high on their agenda. I'm not sure what the upstream stance on non-systemd reliability is - a simple sleep patch is unlikely to be accepted upstream (IMO). While built-in wait loop for PipeWire to initialize may raise concerns about handling of failure modes where something has gone wrong and it will never show up (after all, systemd ensures that dependent units are started when the dependency is ready or that they will fail, too). And I'm not sure if upstream will be happy about re-implementing part of systemd core features inside WirePlumber either. It may be more acceptable on our part for someone interested to improve the launcher script to do a wait on the PipeWire socket before starting pipewire-pulse and wireplumber (while ensuring that it * does not loop forever * cleans up if the socket does not show up or pipewire daemon fails to initialize and maybe tries a second time * preferably can also predict where the socket will show up based on environment variables set * gracefully exit with error message if D-Bus is missing, instructing user on how to fix the issue * etc * ideally written in POSIX Shell while being highly reliable and predictable (since C would be a tall order to accept and probably even PMS approved Bash 4.3 might be a stretch for a launcher) If this sounds like a silly amount of work to badly and only partially re-implement what is already there, then you already know why we are using systemd instead (and also why we went with sleep 1 instead). ;)
Also, /usr/bin/gentoo-pipewire-launcher kills all daemons at every execution, which is annoying, because every time AwesomeWM being restarted, youtube video/music stops playing. Currently I use following script instead: ### if ! pgrep -U "$USER" -f /usr/libexec/xdg-desktop-portal &>/dev/null; then if [[ -x /usr/libexec/xdg-desktop-portal ]]; then /usr/libexec/xdg-desktop-portal & sleep 1 fi fi # The core daemon which by itself does probably nothing. if ! pgrep -U "$USER" -x pipewire &>/dev/null; then /usr/bin/pipewire & /usr/bin/pipewire -c pipewire-pulse.conf & # Hack for bug #822498 sleep 1 fi # Finally a session manager is required for PipeWire to do anything. if ! pgrep -U "$USER" -x wireplumber &>/dev/null; then exec /usr/bin/wireplumber fi ###
(In reply to Niklāvs Koļesņikovs from comment #9) > Regarding WirePlumber, the primary use case of systemd works reliably > (ignoring the previously hidden Gentoo issues that WirePlumber uncovered in > other components), so I doubt non-systemd is high on their agenda. I'm not > sure what the upstream stance on non-systemd reliability is - a simple sleep > patch is unlikely to be accepted upstream (IMO). While built-in wait loop > for PipeWire to initialize may raise concerns about handling of failure > modes where something has gone wrong and it will never show up (after all, > systemd ensures that dependent units are started when the dependency is > ready or that they will fail, too). It's not only that systemd ensures reliability – its trick is to establish the PipeWire socket before actually starting PipeWire (or any other user services), so that even if WirePlumber starts earlier, it is already able to connect() to that socket without issues. (The connect call will block until PipeWire is ready to accept().) The socket handover can be implemented without requiring systemd (although, unfortunately, not in Bash nor POSIX sh) -- for example, I wrote this a few minutes ago for someone on IRC: https://git.nullroute.lt/cgit/hacks/sd-activate.git/tree/ $ ./sd-activate --listen=$XDG_RUNTIME_DIR/pipewire-0 --keepenv --fork pipewire The socket is then ready while PipeWire is still initializing, without timers. This mostly mimics what pipewire.socket does in systemd, though it has the same failure handling as "pipewire &" in the current launcher (i.e. none whatsoever).
I got this issue on my old slow device. The 1 second wait before starting wireplumber is not enough. I changed it to 3 and now the audio does launch right on boot. Pls. add an parameter to the script with default 1, so it is possible to change the value in .config/gentoo-pipewire-launcher.conf
Hopefully we wouldn't need a parameter that would be fixing things out of the box. If not a socket handover, maybe the startup script could monitor for the presence of the needed socket being there already or not, check occasionally (every 100ms?) up to 5 seconds or so, as to still start fast, but not fail wen it's on a slower machine?
After years of using "sleep 1", I've decided to revisit this. I'm "solving" it by essentially busylooping until the socket shows up[1]. The only thing is that I also had a problem with knowing when "wireplumber" *itself* is ready, as programs like polybar would not show the volume applet if it isn't. I'm solving this by busylooping the "amixer get Master" command. Both of these loops run in parallel, and have a timeout, after which they just give up and leave the environment half-setup. This practically never happens, but I also can't really think of a good failure mode that wouldn't invole restarting the environment anyway. I'm using KillUserProcesses=yes in elogind. Looking around at what other distributions do, an interesting proposition is what slackware does[2], which uses a program called daemon[3] that essentially re-runs the pipewire-related daemons if they crash, and allows them to exit once the elogind session is over with "--bind". I've yet to look at other systemd-free distributions, but I fear most of them either still use pulseaudio by default or nab the current script from gentoo as-is. I think it's due time to fix this situation. Ideally there'd be an upstream program, akin to "start-pulseaudio-x11", that forks the necessary daemons and only exits when they're completely up and running. If upstream has no interest, we can always expand the gentoo-pipewire-launcher to do this, though I think Niklāvs' list of requirements is *very* imposing and anything would be preferable to get rid of "sleep 1". For example, I have no idea why "cleaning up" is any useful, when it doesn't make the resulting environment any less broken, and the script will rerun everything when it's executed again. And why posix shell is a requirement when we already have a history of small C programs in the tree (app-text/manpager), and failing that, distfiles could always be used, so any other language like Python is fair game as well. You don't need to do everything systemd does to get acceptable behavior, in this case. Keep it simple. I think Mantas' solution has promise as well, and might be worth exploring instead of proposed busyloops (anything involving kernel-side locks is better :), though it doesn't deal with knowing when programs like "volumeicon" won't crash directly on startup. Does anyone have any other examples? Has there been any form of discussion regarding this with upstream? [1]: https://github.com/mid-kid/config/blob/20642c62a5063fe7f8c496f7553a8e42c1bed0fc/i3/.config/i3/autostart#L7-L14 [2]: https://www.linuxquestions.org/questions/slackware-14/using-pipewire-instead-of-pulseaudio-in-slackware-15-a-4175693980/ [3]: https://github.com/raforg/daemon/
(In reply to Esteve Varela Colominas from comment #14) > Looking around at what other distributions do, an interesting proposition is > what slackware does[2], which uses a program called daemon[3] that > essentially re-runs the pipewire-related daemons if they crash, and allows > them to exit once the elogind session is over with "--bind". Hi, Additionally to my desktop Gentoo, I use Devuan on a laptop with sway/wayland and among other things, daemon is indeed suggested here: https://dev1galaxy.org/viewtopic.php?pid=47569#p47569. Regards.
(In reply to Esteve Varela Colominas from comment #14) > Does anyone have any other examples? Has there been any form of discussion > regarding this with upstream? OpenRC has a supervise-daemon(8) which appears to do a similar thing to the `daemon` program above. It'd avoid having to install yet more software if it can be made to work in this context. My current method is runit/runsvdir to start pipewire and related processes (with automatic wait/retry), put them into a single shared cgroup, and then pipewire's exit handler uses cgroup.kill instead of pkill/pwait. It's too far out there to seriously suggest to others but maybe something similar with openrc and libcgroup could work.
The imposing list of requirements arose from a discussion with a Gentoo developer, since the only way this is going into the distro is if you convince someone with commit rights to actually merge your work. If you tick all the boxes, there's good chance it will go in. Think of it like a job application - maybe you can get hired without ticking all the boxes but who knows. Best of luck on this.
Thankfully open source contribution isn't as one-sided as recruitment... It's not a list of demands to fulfill, but a conversation. I'm just proposing that incremental improvements can be made instead of gunning for perfection or nothing, and that a simple solution may make a lot of sense here. Anyway I'm replying here again because my solution broke[1]. I'm not sure why and how, but now I'm getting race conditions again where audio-related programs start before wireplumber is up, sometimes. I've yet to debug this further, but I think my wait_alsa() function doesn't make a lot of sense. Pipewire and wireplumber still start in the correct order, but I wonder how to properly detect when wireplumber is up. Then again, my method may be too complex and brittle. I like the solutions involving supervision daemons as well, they're very simple and less brittle, but some programs like polybar will launch in a degraded state (no volume slider) if wireplumber isn't up by that time, so it'd be cool to be able to have a script or command that only exits when the entire audio system has been initialized. (In reply to Enne Eziarc from comment #16) > OpenRC has a supervise-daemon(8) which appears to do a similar thing to the > `daemon` program above. It'd avoid having to install yet more software if it > can be made to work in this context. I've dabbled a bit with start-stop-daemon and supervise-daemon in a non-root context before, but I find it hard to remember the exact incantations to make it not complain about not being ran as root, so I'm not sure how to use it like that. Aside from that, I quite like that `daemon` itself can hook into the elogind session and exit when the user logs out. Maybe something can be implemented to use `daemon` if available or fall back to `supervise-daemon` if not? [1]: https://github.com/mid-kid/config/commit/a7b5098acc34ba19b1cc1a8df010d7bf8d74c55d
Sorry in advance, if I'm wrong or you already checked this but I'd probably start by adding an echo or similar debugging mechanism to make sure wait_pipewire is not falling through the 10 second timeout and if it is, then the most likely cause is that the socket location is somewhere else other than the location being checked. I can't recall the details but, I think, there have been cases where some systems have the location switching around based on the state of the environment at the time pipewire executable was started. There may or may not be a way to also check for WirePlumber being ready but I was not paying attention when WirePlumber 0.5 series was making changes around that. After a bit of crude trial and error on my system, I think, you have correctly identified the presence of the Master mixer control as a viable method for checking that pipewire and wireplumber are ready, since the PipeWire ALSA device is not accessible without pipewire daemon running and the Master mixer control only shows up once WirePlumber is done initializing. If that is not working reliably for you, my first guess would be that WirePlumber is either starting before PipeWire or expecting that pipewire-0 socket is located somewhere else. I don't think I can provide any more insight than that, so this is it from me.
> the Master mixer control only shows up once WirePlumber is done initializing I've finally gotten around to debugging a little, and changed my wait_alsa function to look like this: wait_alsa() { for x in $(seq 100); do # ~10s timeout echo "Waiting for alsa..." amixer get Master && amixer get Master && amixer get Master && return 0 sleep .1 done return 1 } Note in particular, how the "amixer" command is ran thrice now. I'm trying to visualize race conditions. In this test, I'm running "while echo 3 | sudo tee /proc/sys/vm/drop_caches; do sleep 1; done" in the background, to help provoke this race condition more than once after each bootup. The interesting bit is, the log now looks like this: Waiting for alsa... Simple mixer control 'Master',0 Capabilities: pvolume pswitch pswitch-joined Playback channels: Front Left - Front Right Limits: Playback 0 - 65536 Mono: Front Left: Playback 65536 [100%] [on] Front Right: Playback 65536 [100%] [on] Simple mixer control 'Master',0 Capabilities: pvolume pvolume-joined pswitch pswitch-joined Playback channels: Mono Limits: Playback 0 - 65536 Mono: Playback 0 [0%] [on] amixer: Unable to find simple control 'Master',0 Waiting for alsa... Simple mixer control 'Master',0 Capabilities: pvolume pswitch pswitch-joined Playback channels: Front Left - Front Right Limits: Playback 0 - 65536 Mono: Front Left: Playback 38011 [58%] [on] Front Right: Playback 38011 [58%] [on] ( ... snip, this message displays verbatim 3x, it booted up correctly, now ... ) It seems that during the startup of wireplumber, the sound device becomes available very shortly, before disappearing again, and becoming available again. For now, I will "debounce" the signal by doing "amixer get Master && sleep .1 && amixer get Master", but I wonder if there would be a way to distinguish the "incomplete" alsa setup from the "complete" one. Maybe "wpctl" is useful? In the long run I'd like to solidify this into a proper script/program, and use inotify/etc properly instead of polling, but I'm just properly confused as to this behavior, lol.