GNOME Bugzilla – Bug 507527
Mixer eats 100% cpu when audio device goes away
Last modified: 2010-10-03 11:31:30 UTC
Please describe the problem: When an audio device (say a USB headset) is removed while gnome-mixer-control is currently open on that device, the app starts eating 100% cpu. The application is otherwise usable. When the device is changed, cpu consumption returns to normal. Steps to reproduce: 1. Connect USB headset 2. Open mixer and set to USB headset device 3. Unplug USB headset. Actual results: gnome-mixer-control eats 100% CPU. Expected results: When the device is unplugged, gnome-mixer-control should switch to another device, and remove the unplugged device from the device list. Does this happen every time? Yes, it is consistently reproduceable. Other information:
Oops: s/gnome-mixer-control/gnome-volume-control/g :)
Hi! Can you be more precise about where that happen in the code? (with GST_DEBUG, using a debugger, and hitting ctrl-c...) Can you check if the same apply to the volume applet (if you select the same device via Preferences)? thanks
I should tell you that I tried to mimic this bug by removing a PulseAudio mixer, but that did not change the cpu usage. Someone with a pluggable audio device could try to help if you don't know what I mean about locating the issue in the code.
*** Bug 485987 has been marked as a duplicate of this bug. ***
ok, I debugged this a bit. After the usb device is removed, and the cpu usage is 100%, the backtrace looks like this:
+ Trace 206887
Thread 2 is the one doing the cpu hogging, and it seems to be stuck in the gst_task_func() in gstreamer. That doesn't seem very surprising, as gnome-volume-control never ever checks if a device is perhaps added or removed. what apparently happens, is that it keeps polling the non-existing device. The actually poll call on line 416 of gstalsamixer.c (from gst-plugins-base) is this: | poll (pfds, rnfds + 1, -1); i.e., a poll with infinite timeout. Unfortunately, gstreamer doesn't check the return value of poll, so if the device disappears, the poll() will return immediately with an error rather than waiting indefinately, and gstreamer will keep calling the function and cause the cpu hog. I think what should happen, is that gstreamer should properly check if the device still exists, and if it disappears, throw some kind of signal for the mixel application to catch. The mixer can then properly get rid of the disappeared mixer. And of course, the mixer needs some way to figure out if new devices are added to the system.
moving it to gstreamer.
I reported a very similar but not identical bug in Ubuntu, bug 400820. https://bugs.launchpad.net/ubuntu/+source/gnome-media/+bug/400820?comments=all However, the bug only started happening about a week ago, under Karmic Studio, and I have had the same system configuration for 2 years, so it's probably appropriate that I enter another bug, and I will do so.
Created attachment 171590 [details] [review] Remove POLLHUP|POLLERR from pollfd->events The POLLHUP and POLLERR are output only, no point specifying them in pollfd->events
Created attachment 171591 [details] [review] Pass all known revents to ALSA handlers Especially, call to ALSA for POLLNVAL and POLLERR, so that it has a chance to cleanup. Alas, it didn't work...
This may be also an error in ALSA library: even after modification of gstreamer to pass all returned poll events to ALSA's snd_mixer_handle_events (see the attached patches), the file descriptor which went invalid with the disconnected device still seems to be returned by snd_mixer_poll_descriptors, which causes poll to return immediately with POLLNVAL|POLLERR (and POLLIN, of course). Maybe, as a sensible workaround (I can imagine the reconfiguration in ALSA to be very complex), reinitialize (as in: close and reopen) the mixer data structures?
BTW, why is the bug UNCONFIRMED? What more of a confirmation is needed?
(In reply to comment #5) > | poll (pfds, rnfds + 1, -1); > > i.e., a poll with infinite timeout. Unfortunately, gstreamer doesn't check the > return value of poll, so if the device disappears, the poll() will return > immediately with an error rather than waiting indefinately, and gstreamer will > keep calling the function and cause the cpu hog. BTW, poll will NOT return with an error. A non-handle (or a closed handle) passed to poll does not cause it to fail, to return the corresponding pollfd->revents with the flag POLLNVAL (which is *almost* the case here). The poll(2) will return a valid return value stating number of elements in the passed array of pollfd structures with .revents field set to non-0.
Created attachment 171619 [details] [review] A crude workaround to avoid looping on removed mixer device This helps the case. The gstreamer monitor task does not loop uselessly polling the hangup device anymore. But it really is not a good fix for the real problem: the users of the gstreamer's mixer interface must somehow get notified that the mixer is not good anymore to act on that. P.S. the strange "if (!mixer->available) nfds = 0;" is so strange to satisfy the debian patch queue. The patch which conflicted made a lot of sense to me (missing mutex unlock) so I tried to keep it applicable (just in case distributions monitor the bug better than gstreamer developers).
All the patches above are against gst-plugins-base 0.10.22 (some old Ubuntu)
... and the bug seem to be fixed since April 2010 in git master (commit 1e8f3f768953cf4a4eeaab2fd76409f61d9f0009 by Sebastian Dröge)
Ok, then let's close this as a duplicate of bug #614545. Thanks *** This bug has been marked as a duplicate of bug 614545 ***