[pulseaudio-discuss] Releasing stream resources when the client receives SIGSTOP

David Henningsson david.henningsson at canonical.com
Mon Nov 24 06:10:07 PST 2014



On 2014-11-24 14:18, Tanu Kaskinen wrote:
> On Mon, 2014-11-24 at 13:10 +0100, David Henningsson wrote:
>>
>> On 2014-11-24 12:04, Tanu Kaskinen wrote:
>>> On Mon, 2014-11-24 at 11:12 +0100, David Henningsson wrote:
>>>>
>>>> On 2014-11-20 04:44, Ricardo Salveti wrote:
>>>>> Hey,
>>>>>
>>>>> When investigating the issue we had on Ubuntu Touch, described by bug
>>>>> https://bugs.launchpad.net/ubuntu-rtm/+source/pulseaudio/+bug/1391230,
>>>>> I noticed that PulseAudio never releases the resources used by an
>>>>> active stream if the app gets a SIGSTOP, keeping pulse busy and
>>>>> consuming cpu until the app resumes or is closed by the user.
>>>>>
>>>>> On Ubuntu Touch that happens when the application is active playing
>>>>> audio/video, and the user moves back to the home scopes (Ubuntu Touch
>>>>> lifecycle will automatically send a SIGSTOP after 5 seconds). When
>>>>> checking that on my desktop, I also noticed that the same happens (by
>>>>> forcing a SIGSTOP against mplayer, for example). Pulse only releases
>>>>> the stream when the app pauses the stream, not necessarily when the
>>>>> app stops after receiving the signal.
>>>>>
>>>>> I raised this first with David to understand if it was indeed a valid
>>>>> use case, and he said that it was indeed something that it was
>>>>> probably never really considered
>>>>> (https://bugs.launchpad.net/ubuntu-rtm/+source/pulseaudio/+bug/1391230/comments/8).
>>>>>
>>>>> So before going and trying to deep dive and find a fix for the issue,
>>>>> I first wanted to understand from you guys if this is indeed a valid
>>>>> issue and what would be the best way to get this fixed. I know we're
>>>>> still using Pulse 4.0 on Ubuntu, but wanted to make sure to get
>>>>> something that would also be compatible with upstream.
>>>>
>>>> So when I discussed this with Ricardo, my suggestion was that we either
>>>>
>>>>     1) (ab)use the cork mechanism to stop/resume the client when we
>>>> discover that the client is SIGSTOPped, or
>>>
>>> This implies that we implement server-side corking, because currently
>>> the cork status is controlled by the client, and this "stalled" corking
>>> would be controlled by the server.
>>>
>>> Even though I have mentioned the "server-side corking" feature before
>>> (as something that we need and use in Tizen), I might not have explained
>>> how I think it should be implemented (Tizen's current implementation is
>>> less flexible than what I'd like). We should have a hashmap of "cork
>>> requests" in sink inputs and source outputs. The stream would be corked
>>> as long as the hashmap isn't empty, i.e. as long as someone thinks that
>>> the stream should be corked. The hashmap keys would be strings
>>> identifying the "corking reasons", so policy modules could easily add
>>> new reasons. The normal client-initiated corking would be one corking
>>> reason, and this stall detection would be another reason. Tizen's policy
>>> module would implement a third reason.
>>
>> +1 in general for this idea, to consolidate the "stall" concept with the
>> "server side cork" concept; the fewer concepts on the more use cases,
>> the better :-)
>>
>> I wonder what we should do with the "cork requests" though. I feel under
>> this scheme, we should deprecate them and replace them with a "you have
>> been (un)corked" message, possibly including the different reasons as
>> strings, so the client can determine whether the cork happened because
>> the client requested so, or if it was for some other reason.
>
> I'd vote for not removing the old cork request feature, because there
> are applications relying it. If the feature is seen as unnecessary for
> new/updated applications, I'm ok with marking it as deprecated in the
> documentation.
>
> As for sending some new kind of message like "you've been corked", I
> don't think that's necessary. If the introspection API allows pactl to
> show the cork status, including corking done by the server (possibly
> also including the reason string(s)), then the introspection API should
> be sufficient also for applications that need to get notified when their
> own stream gets corked by the server.

And if the reasons change, that gives an event/notification on the stream?

> Talking about the client API, there's the question that how should
> pa_sink_input_info.corked and pa_stream_is_corked(). For backwards
> compatibility reasons, I think at least pa_stream_is_corked() should
> return 1 only if the stream is corked by the application, and possibly
> it would be good to apply the same policy for pa_sink_input_info.corked
> too (but I think changing the pa_sink_input_info.corked semantics is
> less likely to cause breakage).
>
> Hmm... I realized there's another problem with stopped clients: not only
> do their streaming get stalled, but they also stop reading events that
> they may be subscribed to. The code looks like the daemon will buffer
> data until it runs out of memory, which seems like a bad idea...
>
> Let's assume that there's a simple application that just subscribes to
> events and does nothing else ("pactl subscribe" would fit the
> description). What to do when such application gets stopped? How do we
> notice that it's stopped, if it's not streaming? Should we send a ping
> message periodically? Or should we keep track of the amount of queued
> data, and if that reaches some threshold, then we consider that client
> stopped? Once we have declared the client unresponsive, should we
> disconnect it, or just drop subscription events until it becomes
> responsive again? In the latter case I think we should notify the
> application that events have been dropped.

I think most apps would like to receive buffered events once they are 
unstopped, so that should be the best for shorter stops.

But I also think it would be better to disconnect the client in case of 
overflow, rather than dropping events. The advanced clients should be 
able to deal with disconnect/reconnect and would then re-read the 
current state after reconnection.

Or we could generalise this: by dealing with this on the 
iochannel/srbchannel level, i e, we could disconnect the client in case 
the pstream.send_queue gets too large? That should at least protect the 
PulseAudio server from OOM, both for notifications and recording streams.

If the send_queue has more than, say, 100 [1] messages, we start a timer 
for 30 [1] seconds. If the send_queue is empty, we stop the timer. If 
the timer expires, the client is disconnected. How about that?

-- 
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic

[1] Subject to bikeshedding


More information about the pulseaudio-discuss mailing list