GNOME Bugzilla – Bug 640255
Using ALSA mixer, GSource and g_thread_init() results in busy loop
Last modified: 2011-10-03 05:53:55 UTC
I'm working on a Gtk+/GLib-based project that needs to monitor the ALSA mixer for external changes in order to keep the internal state up-to-date. The attached program is stripped down to the minimum required to demonstrate the problem I'm seeing (I'm also attaching a small makefile). This happens for glib 2.26.1 and with latest master. This is what happens: the ALSA mixer is opened and initialized, and a GSource created to monitors the file descriptor (to /dev/snd/controlC0 in my setup) acquired from ALSA. That source is then added to the main loop and the main loop is run. If I run the attached program without parameters everything works as expected and the underlying poll() call blocks while waiting for something to happen on the ALSA mixer source. If I open alsamixer in a separate terminal and change the controls, I can also see that the events are handled properly by the mixer source functions. However, if I run the program with an argument (it does not matter what, it's just to differentiate both code paths) things go awry. The only difference is that now g_thread_init(NULL) is called at startup, with the result of the main loop running busy. I've run the program through strace to see what's going on, and what I'm seeing is that some file descriptor (one end of a pipe in fact) is continuously being written with the character 'A', therefore unblocking the poll() call via the other end of the pipe. I was able to track down the pipe write to g_main_context_wakeup_unlocked(), but I am at a complete loss trying to understand what would trigger these continuous calls. Can anybody shed some light on this situation? Cheers, Thierry
Created attachment 179032 [details] test program
Created attachment 179034 [details] makefile for your convenience
So it turns out this is not a bug. Rather it looks like g_source_add_poll() and g_source_remove_poll() should never be called from a source's prepare function, because they eventually end up calling g_main_context_wakeup_unlocked(), which in turn will wake up the underlying poll() call, upon which the prepare function will again be called and so on. Perhaps this should be documented somewhere to make it harder to misuse this in the future? Otherwise I think this bug can be closed.