llvmpipe: Work around WSL 1 missing support for memfd_create()
WSL version 1 has a known limitation that the kernel does not support the memfd_create() syscall, and it always returns -1 (see https://github.com/microsoft/WSL/issues/3542). This results in lavapipe/llvmpipe failing to create the anonymous file it needs for allocations from the pipe_screen object, which in turn results in results in failed application calls to Vulkan APIs (in the case I observed, vkMapMemory returned an invalid (0xffffffff) pointer along with VK_SUCCESS, leading to the application segfaulting). This issue can be reproduced by simply running `vkcube` (or, presumably any other simple Vulkan application) inside WSL 1, e.g.: xvfb-run -s '-screen 0 1024x768x24' vkcube --c 300 This patch addresses the issue with several changes: 1. llvmpipe_create_screen() now checks for errors from the os_create_anonymous_file function and errors out early, making it easier to track down issues similar to this. Previously, the invalid fd of -1 would be stored in the pipe_screen struct and the problems would only appear later. 2. os_create_anonymous_file() now attempts to handle the case where memfd_create() fails, by falling back to creating a file in a temporary directory. This fallback is the same as is already done for builds that don't have memfd_create available at build time - note that the difference here is that this is a _runtime_ fallback, as is needed for the case of WSL 1. 3. The fallback logic previously relied on the XDG_RUNTIME_DIR environment variable, which might not be set when running inside WSL because there is unlikely to be a desktop environment configured. This patch adds a fallback of creating a new directory inside /tmp in this case. Reviewed-by: Lucas Fryzek <lfryzek@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37679>
This commit is contained in:
parent
85b170ab41
commit
b79013ead9
2 changed files with 94 additions and 20 deletions
|
|
@ -1031,6 +1031,11 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
|
|||
util_vma_heap_init(&screen->mem_heap, alignment, UINT64_MAX - alignment);
|
||||
screen->mem_heap.alloc_high = false;
|
||||
screen->fd_mem_alloc = os_create_anonymous_file(0, "allocation fd");
|
||||
if (screen->fd_mem_alloc == -1) {
|
||||
mesa_loge("Failed to create anonymous file for memory allocations\n");
|
||||
llvmpipe_destroy_screen(&screen->base);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
snprintf(screen->renderer_string, sizeof(screen->renderer_string),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
* Copyright (C) 2025 Arm Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
|
|
@ -42,11 +43,16 @@
|
|||
#elif DETECT_OS_ANDROID
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/memfd.h>
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if !(defined(__FreeBSD__) || DETECT_OS_ANDROID)
|
||||
#include "log.h"
|
||||
#include "os_misc.h"
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(HAVE_MKOSTEMP) || DETECT_OS_ANDROID)
|
||||
#if !(defined(__FreeBSD__) || defined(HAVE_MKOSTEMP) || DETECT_OS_ANDROID)
|
||||
static int
|
||||
set_cloexec_or_close(int fd)
|
||||
{
|
||||
|
|
@ -70,7 +76,7 @@ err:
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || DETECT_OS_ANDROID)
|
||||
#if !(defined(__FreeBSD__) || DETECT_OS_ANDROID)
|
||||
static int
|
||||
create_tmpfile_cloexec(char *tmpname)
|
||||
{
|
||||
|
|
@ -95,6 +101,61 @@ create_tmpfile_cloexec(char *tmpname)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !(defined(__FreeBSD__) || DETECT_OS_ANDROID)
|
||||
/*
|
||||
* Gets the path to a suitable temporary directory for the current user.
|
||||
* Prefers using the environment variable `XDG_RUNTIME_DIR` if set,
|
||||
* otherwise falls back to creating or re-using a folder in `/tmp`.
|
||||
* Copies the path into the given `buf` of length `len` and also returns
|
||||
* a pointer to the same buffer for convenience.
|
||||
* Returns NULL if no suitable directory can found or created.
|
||||
*/
|
||||
static char*
|
||||
get_or_create_user_temp_dir(char* buf, size_t len) {
|
||||
const char* env;
|
||||
struct stat st;
|
||||
int uid = getuid();
|
||||
|
||||
env = os_get_option("XDG_RUNTIME_DIR");
|
||||
if (env && env[0] != '\0') {
|
||||
snprintf(buf, len, "%s", env);
|
||||
return buf;
|
||||
}
|
||||
|
||||
snprintf(buf, len, "/tmp/xdg-runtime-mesa-%ld", (long)getuid());
|
||||
mesa_logd("%s: XDG_RUNTIME_DIR not set; falling back to temp dir %s",
|
||||
__func__, buf);
|
||||
if (stat(buf, &st) == 0) {
|
||||
/* If already exists, confirm the owner/permissions */
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
mesa_loge(
|
||||
"%s: %s exists but is not a directory", __func__, buf);
|
||||
return NULL;
|
||||
}
|
||||
if (st.st_uid != uid) {
|
||||
mesa_loge(
|
||||
"%s: %s exists but has wrong owner", __func__, buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
} else if (errno == ENOENT) {
|
||||
/* Doesn't exist, try to create it */
|
||||
if (mkdir(buf, 0700) != 0) {
|
||||
mesa_loge("%s: mkdir %s failed: %s", __func__, buf,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
} else {
|
||||
mesa_loge("%s: stat %s failed: %s", __func__, buf,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create a new, unique, anonymous file of the given size, and
|
||||
* return the file descriptor for it. The file descriptor is set
|
||||
|
|
@ -116,7 +177,8 @@ create_tmpfile_cloexec(char *tmpname)
|
|||
int
|
||||
os_create_anonymous_file(int64_t size, const char *debug_name)
|
||||
{
|
||||
int fd, ret;
|
||||
int fd = -1, ret;
|
||||
/* First try using preferred APIs */
|
||||
#if defined(HAVE_MEMFD_CREATE)
|
||||
if (!debug_name)
|
||||
debug_name = "mesa-shared";
|
||||
|
|
@ -132,26 +194,33 @@ os_create_anonymous_file(int64_t size, const char *debug_name)
|
|||
fd = shm_mkstemp(template);
|
||||
if (fd != -1)
|
||||
shm_unlink(template);
|
||||
#else
|
||||
const char *path;
|
||||
char *name;
|
||||
#endif
|
||||
|
||||
path = getenv("XDG_RUNTIME_DIR");
|
||||
if (!path) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* If preferred API failed (or not included in this build),
|
||||
* fall back to using a file in a temporary dir
|
||||
*/
|
||||
#if !(defined(__FreeBSD__) || DETECT_OS_ANDROID)
|
||||
if (fd == -1) {
|
||||
char path[PATH_MAX];
|
||||
char *name;
|
||||
|
||||
if (debug_name)
|
||||
asprintf(&name, "%s/mesa-shared-%s-XXXXXX", path, debug_name);
|
||||
else
|
||||
asprintf(&name, "%s/mesa-shared-XXXXXX", path);
|
||||
if (!name)
|
||||
return -1;
|
||||
if (!get_or_create_user_temp_dir(path, sizeof(path))) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = create_tmpfile_cloexec(name);
|
||||
if (debug_name)
|
||||
asprintf(&name, "%s/mesa-shared-%s-XXXXXX", path, debug_name);
|
||||
else
|
||||
asprintf(&name, "%s/mesa-shared-XXXXXX", path);
|
||||
if (!name)
|
||||
return -1;
|
||||
|
||||
free(name);
|
||||
fd = create_tmpfile_cloexec(name);
|
||||
|
||||
free(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fd < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue