On Sat, 2018-04-07 at 10:14 -0700, René J.V. Bertin wrote: > On Saturday April 07 2018 18:42:27 Tanu Kaskinen wrote: > > Hi, > > > I cc'd a few people who have contributed to PulseAudio's macOS support > > I have a vague memory that PulseAudio has little to do on Mac, > something I tend to agree with. I use a lot of FOSS applications but > none that work only with PA, so while I have libpulse installed for > dependency reasons, I do not have the pulseaudio daemon itself. > I also recall that back when I still did use PA for some > applications, I had to launch the daemon manually. > > I think there are several alternatives to look at > - get rid of all unsafe API calls between fork and exec; this is what > we did with KDE's KInit framework for instance. I have not had any > feedback (yet) that the result doesn't work on 10.13 . Is calling close() safe? If it is, then this option seems feasible. The clever stuff that pa_close_all() does could be done before fork(), and only the close() calls need to be done after fork(). There's also the spawn_api.atfork() callback call, which is potentially unsafe, but it's very unlikely that the callback is set. > Why would PA need to call ObjC APIs while auto-spawning? PA doesn't have any ObjC code, but applications using libpulse may have. I don't know what the ObjC runtime does that affects the forking behaviour of libpulse, maybe it sets some process settings in the kernel. > - The PA daemon can be launched manually so there's apparently no > reason to spawn it with fork+exec; the system() call should do nicely > too. Hmm... maybe. > - Supposing that having a sound daemon is not a crucial aspect: > integrate the actual sound playing functionality into libpulse on > Mac. Not going to happen. > - Use LaunchServices with a similar approach as used for the session > D-Bus or even by XQuartz. These use a mechanism where the daemon > (agent) is registered as an on-demand service which is accessible via > a named socket. The socket name is published in an env. variable > (DISPLAY for XQuartz), and launchd will start the daemon when an > application connects to the socket. I don't know the exact details > and to what extent it will be possible to use a self-determined > socket name that is not exported via an env. variable but that > shouldn't be too hard to find out (or adapt to, if indeed use of an > env. variable is obligatory). > > The LaunchServices approach is undoubtedly the cleanest solution, but > I don't see anything wrong to using system() either. Yes, using a service seems like the best option. > > environment variables from libpulse (it's not thread-safe, and messing > > If all else fails ... What is the chance that multiple threads would > try to spawn the PA daemon at the same time? A mutex should make that > impossible. There's of course the possibility that another thread > would also be spawning or launching a child process and I understand > that OBJC_DISABLE_INITIALIZE_FORK_SAFETY has to be set before calling > fork() (so the exec() variants that take an environment argument > aren't a solution) - there must be a way for a thread to preempt all > others for a short duration? Yeah, just setting the environment variable doesn't seem terribly dangerous, just ugly due to breaking the rule of "never set environment variables of other people's programs from your library". -- Tanu https://liberapay.com/tanuk https://www.patreon.com/tanuk