vulkan/wsi/x11: Refuse to connect to thread-unsafe Displays
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

We heavily rely on threading in Vulkan WSI.  There's no way this is safe
if XInitThreads() hasn't been called.  Fortunately, this should never be
the case since 2022 or so.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13530
Cc: mesa-stable
Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36120>
This commit is contained in:
Faith Ekstrand 2025-07-14 10:38:12 -04:00 committed by Marge Bot
parent 6286c1c66f
commit cf654be16b

View file

@ -21,6 +21,7 @@
* IN THE SOFTWARE.
*/
#include <X11/Xlibint.h>
#include <X11/Xlib-xcb.h>
#include <X11/xshmfence.h>
#define XK_MISCELLANY
@ -609,18 +610,42 @@ wsi_GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
return true;
}
static bool
xlib_display_is_thread_safe(Display *dpy)
{
/* 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'.
* It will be NULL if XInitThreads wasn't called.
*/
return dpy->lock_fns != NULL;
}
VKAPI_ATTR VkBool32 VKAPI_CALL
wsi_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
Display *dpy,
VisualID visualID)
{
/* Our WSI implementation for X11 relies on threads. Check Xlib is running
* in thread safe mode before advertising support.
*/
if (!xlib_display_is_thread_safe(dpy))
return false;
return wsi_GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice,
queueFamilyIndex,
XGetXCBConnection(dpy),
visualID);
}
static bool
x11_surface_is_thread_safe(VkIcdSurfaceBase *icd_surface)
{
if (icd_surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
return xlib_display_is_thread_safe(((VkIcdSurfaceXlib *)icd_surface)->dpy);
else
return true;
}
static xcb_connection_t*
x11_surface_get_connection(VkIcdSurfaceBase *icd_surface)
{
@ -645,6 +670,11 @@ x11_surface_get_support(VkIcdSurfaceBase *icd_surface,
uint32_t queueFamilyIndex,
VkBool32* pSupported)
{
if (!x11_surface_is_thread_safe(icd_surface)) {
*pSupported = false;
return VK_SUCCESS;
}
xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
xcb_window_t window = x11_surface_get_window(icd_surface);
@ -2555,6 +2585,15 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
/* We really shouldn't get here as we return no WSI support for XLib when
* it's not threadsafe. However, one final check doesn't cost much.
*/
if (!x11_surface_is_thread_safe(icd_surface)) {
fprintf(stderr, "vulkan: xlib Display is not thread-safe. Call "
"XInitThreads() in your app\n");
return VK_ERROR_UNKNOWN;
}
/* Get xcb connection from the icd_surface and from that our internal struct
* representing it.
*/