Bug 39459 - Draining playback stream never completes
Summary: Draining playback stream never completes
Status: RESOLVED MOVED
Alias: None
Product: PulseAudio
Classification: Unclassified
Component: clients (show other bugs)
Version: unspecified
Hardware: x86 (IA32) Linux (All)
: medium normal
Assignee: pulseaudio-bugs
QA Contact: pulseaudio-bugs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-21 12:47 UTC by Remi Denis-Courmont
Modified: 2018-07-30 10:21 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments

Description Remi Denis-Courmont 2011-07-21 12:47:21 UTC
I might have missed something obvious but there seems to be a race condition 
resulting in a deadlock in libpulse 0.9.22 (Debian).

I have stream with prebuf disabled (zero). When the Close() function below 
gets called, if the stream is not corked, the pa_stream_drain() callback 
never gets called, so pa_threaded_mainloop_wait() never returns and the whole 
process jams.

This seems timing dependent: if I put a gdb breakpoint on 
pa_operation_get_state() then continue, the callback does get called and the 
process does not get stuck on the condition variable. There is also no problem 
if the stream is corked, in which case we use pa_stream_flush() instead of 
pa_stream_drain().

The code follows:

static void stream_success_cb(pa_stream *s, int success, void *userdata)
{
    pa_threaded_mainloop *mainloop = userdata;

    fprintf(stderr, "DONE: %d\n", success);
    pa_threaded_mainloop_signal(mainloop, 0);
    (void) s;
    (void) success;
}

/* ... */

static void Close(vlc_object_t *obj)
{
    aout_instance_t *aout = (aout_instance_t *)obj;
    aout_sys_t *sys = aout->output.p_sys;
    pa_threaded_mainloop *mainloop = sys->mainloop;
    pa_context *ctx = sys->context;
    pa_stream *s = sys->stream;

    /* ... */

    pa_threaded_mainloop_lock(mainloop);
    if (s != NULL) {
        pa_operation *op;

        if (pa_stream_is_corked(s) > 0)
            /* Stream paused: discard all buffers */
            op = pa_stream_flush(s, stream_success_cb, mainloop);
        else
            /* Stream playing: wait until buffers are played */
            op = pa_stream_drain(s, stream_success_cb, mainloop);
        if (likely(op != NULL)) {
            while (pa_operation_get_state(op) == PA_OPERATION_RUNNING) {
                fprintf(stderr, "waiting\n");
                pa_threaded_mainloop_wait(mainloop);
            }
            pa_operation_unref(op);
        }

        pa_stream_disconnect(s);
        pa_stream_unref(s);
    }
    if (ctx != NULL)
        pa_context_unref(ctx);
    pa_threaded_mainloop_unlock(mainloop);
    pa_threaded_mainloop_free(mainloop);
    free(sys);
}
Comment 1 Arun Raghavan 2012-02-08 22:42:52 UTC
Does this happen with PA 1.x as well?
Comment 2 Remi Denis-Courmont 2012-02-09 09:21:37 UTC
Yes. Reproducible with PulseAudio 1.1 from Debian.
Comment 3 GitLab Migration User 2018-07-30 10:21:22 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/370.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.