[pulseaudio-discuss] Race condition in threaded mainloop

Daniel Mack zonque at gmail.com
Mon Mar 28 03:21:16 PDT 2011


Hi,

when developing PulseAudio clients with a threaded mainloop (on OS X
in my case), I came across an effect which causes my client to crash
out early with a failed assertion like

  Assertion 'c->defer_event == e' failed at
pulsecore/socket-client.c:172, function connect_defer_cb(). Aborting.

Searching for this issue didn't reveal much, except that there has
been other people seeing this:

  https://bugzilla.redhat.com/show_bug.cgi?id=497650

Looking at the code, it seems obvious that this is a simple race
condition. In do_connect(),  pulsecore/socket-client.c:210, we have
this:

  c->defer_event = c->mainloop->defer_new(c->mainloop, connect_defer_cb, c);

and defer_new() calls pa_mainloop_wakeup() before it returns. So in a
threaded mainloop, it could be that the defered event has already been
dispatched before defer_new() returns.
However, c->defer_event is assigned *after* defer_new() returns, and
hence the assertion fails consequently. The same counts for
defer_enable() in some cases, as the event is enabled by default and
could have been executed already, so disabling it after the mainloop
was woken up has no effect.

As this seems so obvious, and the code has been around for some years,
I wonder whether I miss anything obvious here. Is there any mutex
(which doesn't work yet on OS X) that should protect the mainloop from
this race? I attached a patch ready to fix this issue for me, but I'm
not sure whether there is more code left which fails for similar
assumptions.

Thanks,
Daniel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-mainloop-api-fix-race-condition-in-defer_new.patch
Type: application/octet-stream
Size: 11298 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/pulseaudio-discuss/attachments/20110328/dc4ec102/attachment.obj>


More information about the pulseaudio-discuss mailing list