audio volume control application can prevent suspend
This is somewhat similar to bug #1039.
I have a small volume control application (a windowmaker dockapp, actually) that displays the volume level of a selected mixer channel. To follow changes to the volume level done by other volume control applications, it queries the mixer every 50ms.
Ever since I upgraded my system to OpenIndiana-148 last year I had to manually stop this dockapp before suspending the system, as it wouldn't suspend as long as it ran.
I found that audio_control_read() in usr/src/uts/common/io/audio/impl/audio_ctrl.c uses cv_wait() when the device is suspended. Changing that to use cv_wait_sig() and returning EINTR if it failed, as suggested in bug #1039, fixed it for me. The same change could probably be done to audio_control_write() in the same file and to auimpl_engine_setup() and auimpl_engine_close() in usr/src/uts/common/io/audio/impl/audio_engine.c, although it is unlikely that an application uses these functions in a way similar to what my volume control dockapp does.
PS: Is there a way to get notified about volume control changes? SIGPOLL doesn't seem to work.
Updated by Garrett D'Amore over 8 years ago
I'm highly skeptical of the analysis of this fix. Why should this be interruptible? Was the problem a failure to suspend, or a failure to resume? Is this read occurring on some special thread? (The latter makes more sense, and would be the result of failing to broadcast on the cv...) The smbsrv bug was more likely due to a thread that could not suspend, but I'm having a rough time believing that this what is happening here.
With respect to poll, the audio API we adhere to (OSS) doesn't know about poll() or select(), so we didn't implement it (if I recall rightly -- its been a while since I wrote that code.)
Updated by Hans Rosenfeld over 8 years ago
The problem is a failure to suspend, not to resume. The system does not enter the sleep state, the suspend process is aborted:
May 7 18:43:35 bl0rg genunix: [ID 535284 kern.notice] System is being suspended May 7 18:44:08 bl0rg genunix: [ID 520228 kern.warning] WARNING: Suspend cannot stop process wmsmixer -w (ffffff01d94c6860:1). May 7 18:44:08 bl0rg genunix: [ID 903701 kern.warning] WARNING: Process may be waiting for network request, please try again. May 7 18:44:12 bl0rg genunix: [ID 583038 kern.notice] System has been resumed.
The wmsmixer dockapp doesn't do any networking. It does query the audio mixer every 50ms, using an ioctl(), which will eventually lead to audio_control_read(). The suspend failure can be reproduced reliably, it always happens when wmsmixer is running.
I'm not 100% sure about the analysis either, mainly for the reason that I don't know the audio code at all. But the proposed change does fix the problem, and I haven't seen it cause any new problems here.
Updated by Albert Lee over 8 years ago
The device is suspended via a pm request from cpr before the ioctl is called. The read thread is stuck on the sleep queue and when we attempt to stop user threads the thread is apparently never set runnable because state is TS_SLEEP and the T_WAKEABLE flag is unset. The checkpoint flag (which seems to treated as a pending signal state by ISSIG_PENDING) is normally only checked in signal handling.