[pulseaudio-discuss] gnome-shell hangs, waiting for pulse-audio

Tanu Kaskinen tanuk at iki.fi
Mon Dec 3 17:47:06 PST 2012


On Sun, 2012-12-02 at 20:20 +0100, Henrik /KaarPoSoft wrote:
> On 12/02/12 05:49, Tanu Kaskinen wrote:
> > The original backtrace only has the trace for one thread, the thread
> > where the libpulse mainloop runs isn't shown. Could you take a backtrace
> > again, this time with "thread apply all bt"? The libpulse thread might
> > be hanging too (which would explain why the main thread is hanging,
> > since the libpulse thread is responsible for waking up the main thread).
> I have changed Xsession to log client messages to syslog.
> Unfortunatly they all show up with tag Xsession, not the individual client.
> 
> Anyway, I have attached the relevant part of syslog (pulseaudio and 
> Xsession), as well as pulseaudio and gnome-shell backtraces for all 
> threads.

I had a look at the backtrace, and the libpulse thread didn't seem to be
stuck, which was a bit disappointing. (There were actually two libpulse
threads, the other is probably for the volume control. Both were waiting
in poll, so not stuck.)

This is the code in libcanberra that hangs in
pa_threaded_mainloop_wait():

                        /* Let's try to play the sample */
                        if (!(o = pa_context_play_sample_with_proplist(p->context, name, c->device, v, l, play_sample_cb, out))) {
                                ret = translate_error(pa_context_errno(p->context));
                                goto finish_locked;
                        }

                        for (;;) {
                                pa_operation_state_t state = pa_operation_get_state(o);

                                if (state == PA_OPERATION_DONE) {
                                        canceled = FALSE;
                                        break;
                                } else if (state == PA_OPERATION_CANCELED) {
                                        canceled = TRUE;
                                        break;
                                }

                                pa_threaded_mainloop_wait(p->mainloop);
                        }

It looks like the PLAY_SAMPLE message is successfully sent to
pulseaudio, and pulseaudio responds with an error. When receiving the
error, libpulse should call play_sample_cb. This is how play_sample_cb()
looks:

static void play_sample_cb(pa_context *c, uint32_t idx, void *userdata) {
        struct private *p;
        struct outstanding *out = userdata;

        ca_assert(c);
        ca_assert(out);

        p = PRIVATE(out->context);

        if (idx != PA_INVALID_INDEX) {
                out->error = CA_SUCCESS;
                out->sink_input = idx;
        } else
                out->error = translate_error(pa_context_errno(c));

        pa_threaded_mainloop_signal(p->mainloop, FALSE);
}

I can see three things that could cause the hang:

1) play_sample_cb() isn't getting called.

2) The operation state isn't getting set to either PA_OPERATION_DONE nor
PA_OPERATION_CANCELED before calling play_sample_cb().

3) pa_threaded_mainloop_signal() isn't working.

Hmm... I checked when the operation state is set to DONE, and it's not
done until after calling the callback. So, if the kernel schedules the
main thread after the pa_threaded_mainloop_signal() call, but before the
operation state is set to DONE, the main thread will get stuck. It's a
bug in libcanberra. I'll try to come up with a patch for that.

-- 
Tanu



More information about the pulseaudio-discuss mailing list