mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-03 09:01:42 -05:00
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>
This commit is contained in:
parent
81c57614d1
commit
853c24e699
4 changed files with 192 additions and 78 deletions
|
|
@ -126,6 +126,14 @@ void wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode,
|
|||
union wl_argument *args);
|
||||
struct wl_proxy *wl_proxy_create(struct wl_proxy *factory,
|
||||
const struct wl_interface *interface);
|
||||
struct wl_proxy *wl_proxy_marshal_constructor(struct wl_proxy *proxy,
|
||||
uint32_t opcode,
|
||||
const struct wl_interface *interface,
|
||||
...);
|
||||
struct wl_proxy *
|
||||
wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
|
||||
uint32_t opcode, union wl_argument *args,
|
||||
const struct wl_interface *interface);
|
||||
|
||||
void wl_proxy_destroy(struct wl_proxy *proxy);
|
||||
int wl_proxy_add_listener(struct wl_proxy *proxy,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue