client: Introduce functions to allocate and marshal proxies atomically
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 15 Nov 2013 05:29:06 +0000 (21:29 -0800)
committerKristian Høgsberg <krh@bitplanet.net>
Sat, 16 Nov 2013 04:49:36 +0000 (20:49 -0800)
commit853c24e6998f747150e4233cf41bfa8268964cc2
treec9ae09bb76bb6b0e06695e95d1c39f9ee9d4b744
parent81c57614d11787c00b8859cbaef650e284b4f188
client: Introduce functions to allocate and marshal proxies atomically

The server requires clients to only allocate one ID ahead of the previously
highest ID in order to keep the ID range tight.  Failure to do so will
make the server close the client connection.  However, the way we allocate
new IDs is racy.  The generated code looks like:

  new_proxy = wl_proxy_create(...);
  wl_proxy_marshal(proxy, ... new_proxy, ...);

If two threads do this at the same time, there's a chance that thread A
will allocate a proxy, then get pre-empted by thread B which then allocates
a proxy and then passes it to wl_proxy_marshal().  The ID for thread As
proxy will be one higher that the currently highest ID, but the ID for
thread Bs proxy will be two higher.  But since thread B prempted thread A
before it could send its new ID, B will send its new ID first, the server
will see the ID from thread Bs proxy first, and will reject it.

We fix this by introducing wl_proxy_marshal_constructor().  This
function is identical to wl_proxy_marshal(), except that it will
allocate a wl_proxy for NEW_ID arguments and send it, all under the
display mutex.  By introducing a new function, we maintain backwards
compatibility with older code from the generator, and make sure that
the new generated code has an explicit dependency on a new enough
libwayland-client.so.

A virtual Wayland merit badge goes to Kalle Vahlman, who tracked this
down and analyzed the issue.

Reported-by: Kalle Vahlman <kalle.vahlman@movial.com>
src/Makefile.am
src/scanner.c
src/wayland-client.c
src/wayland-client.h