There is no way to cancel wl_display_dispatch(_pending) call without a server roundtrip
@jadahl
Submitted by Jonas Ådahl Assigned to Wayland bug list
Description
Assuming a client is using a multi threaded UI architecture, dispatching on more than one thread, either using the example API usage (wl_display_prepare_read(), poll(fds, 1, -1), ...) or the API helpers wl_display_dispatch() and wl_display_dispatch_queue(), there is currently now good way to make the dispatch call return so that the client can disconnect.
Calling wl_display_disconnect() simply closes the fd and frees the wl_display structure, causing the poll() call to stall and likely a segmentation fault if it leaves it.
Calling pthread_kill() does not work as is, since wl_display_dispatch_queue() will simply re-poll on EINTR.
What one can do is to set a variable causing the dispatcher thread not to continue dispatching and then call wl_display_sync(). This would make the server write data to the fd, causing the dispatcher thread to dispatch and return. This should IMHO only be considered a temporary work-around.
Potentially better solutions could be:
-
Make sure wl_display_disconnect() waits for all registered readers to finish, while making the readers using the helpers cancel using some fd signaling technique like eventfd. A problem with this is that the wl_display_dispatch(_queue) functions would need to return an error (maybe ECANCELED is a reasonable one) This has the side effect that existing clients doing poll(1, -1) and calling wl_display_disconnect() would suddenly start to dead lock. The dead lock could be avoided however by only waiting for wl_display_dispatch_pending() callers, meaning letting the other ones simply continue to deadlock and/or crash in their dispatcher thread as they would before.
-
Introduce new API for canceling wl_display_dispatch(_queue), letting wl_display_disconnect() stay thread unsafe, using some method similar to above. Similar issues as above, but without changing the behavior of wl_display_disconnect().