ttuegel / alsa-mixer

Haskell bindings to the ALSA mixer API
BSD 3-Clause "New" or "Revised" License
7 stars 3 forks source link

getMixerByName is not forkProcess on pulseaudio #1

Closed ikv closed 10 years ago

ikv commented 10 years ago

If process is forked after newForeignPtr, but before finalizer is run, then one of the finalizers will fail due to shared resource (shm) already being freed. In some cases child segfaults too, although I did not found a reliable way to reproduce.

How to reproduce:

module Main where

import Sound.ALSA.Mixer
import System.Posix.Process (forkProcess)
import Control.Monad (void)

main = do
  m <- getMixerByName "default"
  forkProcess (return ()) 
  void $ controls m -- forces foreignPtr liveness

and the output I'm getting:

$ ./test
 shm_unlink(/pulse-shm-2335620294) failed: No such file or directory

Why it's relevant: Because of XMonad. XMonad does all it's forks via forkProcess (see xfork soruce @ XMonad.Core). And if you want to query volume levels from the xmonad then alsa-mixer is the only sane option you got (parsing textual output of amixer is not)

ttuegel commented 10 years ago

Thanks for the report! We should track which process creates each shared resource and only free them in the creating (parent) process.

ikv commented 10 years ago

On 01/15, Thomas Tuegel wrote:

Thanks for the report! We should track which process creates each shared resource and only free them in the creating (parent) process. That kind of approach to issue is never crossed my mind, interesting. Usually resources are managed by limiting scope of liveness. Something, like withMixer :: String -> (Mixer -> IO ()) -> IO (), where Mixer is closed as soon as action is finished. See, for example Foreign.Marshal.Pool.withPool, System.IO.withFile, etc. Could you please elaborate on your decision to check pid instead?

On second thought: ignore me, those things are orthogonal.

ttuegel commented 10 years ago

I've implemented your suggestion as withMixer, which explicitly manages the scope of the Mixer object and checks that the mixer is only freed by the parent process. I've uploaded version 0.2.0 to Hackage, please let me know if you have more problems!

ikv commented 10 years ago

Awesome, thank you. Altho it would be nice, if documentation would specify that it would be Sound.ALSA.Exception.T thrown on error.

Also, it's appears, that on failure snd_mixer_attach does unconditionally spits this error message: ALSA lib control.c:953:(snd_ctl_open_noupdate) Invalid CTL. Is there an easy way to shut it up?