On Wed, Nov 14, 2012 at 3:03 PM, Rémi Denis-Courmont remi@remlab.net wrote:
Le mercredi 14 novembre 2012 21:49:36, Trent Piepho a écrit :
You claim that the Gstreamer ALSA sink plugin accesses alsa-lib from two threads simultaneously. Could you elaborate on how this can happen, maybe it is easy to fix?
gstreamer has no lock around the call to snd_pcm_delay(). So it can race with snd_pcm_wait() or snd_pcm_writei(), which are called in another thread. There is a lock around the block of code calling wait()/writei(), but this lock isn't used for calling delay().
Use non-blocking I/O and poll(). Then the snd_pcm_write() calls will not sleep and can be interlocked with snd_pcm_delay() calls.
gstreamer uses non-blocking I/O. But uses snd_pcm_wait rather than poll directly. I wonder if poll() is entirely correct when ALSA plugins are in the chain?
"the snd_pcm_write() calls ...can be interlocked with snd_pcm_delay() calls".
It's still a race to call writei() and delay() at the same time, even if writei() is non-blocking. But only if the rate plugin is being used. Of course the actual race is very small, and doesn't include the time spent doing resampling or mixing in plugins which are still part of the writei() call in non-blocking mode. It's basically like the BKL around every ALSA call.
It seems that they didn't know there would be a problem.
Eh? It is rather the exception for a library to be thread-safe when using the same object in multiple threads.
It's ok to call kernel syscalls on the same fd at the same time. The kernel used to have the BKL for this. Now it has fine grained locking around the actual critical sections. So if ALSA is called thread safe, it doesn't seem that unreasonable to think one can do this.
It looks more like "they" did not pay attention to what they were doing.
I think the point is that this bug was in gstreamer. gstreamer is commonly used by many people. The bug has been there for years. Many programmers have looked at the code. Yet no one noticed it or tracked it down until now. If it's so obvious why did it take so long?
You aren't aware of this problem in other multi-threaded code, but that doesn't mean it doesn't exist. You weren't aware of the problem in gstreamer and yet it exists.