broadway: Handle shm_open failing by falling back on tmp files
This is required if /dev/shm is not mounted on your system, which can happen for instance in certain container configurations.
This commit is contained in:
@ -825,18 +825,30 @@ map_named_shm (char *name, gsize size)
|
||||
|
||||
int fd;
|
||||
void *ptr;
|
||||
char *filename = NULL;
|
||||
|
||||
fd = shm_open(name, O_RDONLY, 0600);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror ("Failed to shm_open");
|
||||
filename = g_build_filename (g_get_tmp_dir (), name, NULL);
|
||||
fd = open (filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror ("Failed to map shm");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
|
||||
(void) close(fd);
|
||||
|
||||
if (filename)
|
||||
{
|
||||
unlink (filename);
|
||||
g_free (filename);
|
||||
}
|
||||
else
|
||||
shm_unlink (name);
|
||||
|
||||
return ptr;
|
||||
|
||||
@ -524,21 +524,36 @@ _gdk_broadway_server_window_set_transient_for (GdkBroadwayServer *server,
|
||||
}
|
||||
|
||||
static void *
|
||||
map_named_shm (char *name, gsize size)
|
||||
map_named_shm (char *name, gsize size, gboolean *is_shm)
|
||||
{
|
||||
#ifdef G_OS_UNIX
|
||||
|
||||
char *filename = NULL;
|
||||
int fd;
|
||||
void *ptr;
|
||||
int res;
|
||||
|
||||
fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
return NULL;
|
||||
|
||||
filename = g_build_filename (g_get_tmp_dir (), name, NULL);
|
||||
|
||||
fd = open (filename, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
g_free (filename);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
g_error ("Unable to allocate shared mem for window");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
*is_shm = FALSE;
|
||||
}
|
||||
else
|
||||
*is_shm = TRUE;
|
||||
|
||||
res = ftruncate (fd, size);
|
||||
g_assert (res != -1);
|
||||
@ -547,6 +562,9 @@ map_named_shm (char *name, gsize size)
|
||||
res = posix_fallocate (fd, 0, size);
|
||||
if (res != 0 && errno == ENOSPC)
|
||||
{
|
||||
if (filename)
|
||||
unlink (filename);
|
||||
else
|
||||
shm_unlink (name);
|
||||
g_error ("Not enough shared memory for window surface");
|
||||
}
|
||||
@ -579,6 +597,7 @@ map_named_shm (char *name, gsize size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*is_shm = TRUE;
|
||||
res = ftruncate (fd, size);
|
||||
g_assert (res != -1);
|
||||
|
||||
@ -614,7 +633,7 @@ make_valid_fs_char (char c)
|
||||
|
||||
/* name must have at least space for 34 bytes */
|
||||
static gpointer
|
||||
create_random_shm (char *name, gsize size)
|
||||
create_random_shm (char *name, gsize size, gboolean *is_shm)
|
||||
{
|
||||
guint32 r;
|
||||
int i, o;
|
||||
@ -638,7 +657,7 @@ create_random_shm (char *name, gsize size)
|
||||
}
|
||||
name[o++] = 0;
|
||||
|
||||
ptr = map_named_shm (name, size);
|
||||
ptr = map_named_shm (name, size, is_shm);
|
||||
if (ptr)
|
||||
return ptr;
|
||||
}
|
||||
@ -650,6 +669,7 @@ typedef struct {
|
||||
char name[36];
|
||||
void *data;
|
||||
gsize data_size;
|
||||
gboolean is_shm;
|
||||
} BroadwayShmSurfaceData;
|
||||
|
||||
static void
|
||||
@ -660,7 +680,14 @@ shm_data_destroy (void *_data)
|
||||
#ifdef G_OS_UNIX
|
||||
|
||||
munmap (data->data, data->data_size);
|
||||
if (data->is_shm)
|
||||
shm_unlink (data->name);
|
||||
else
|
||||
{
|
||||
char *filename = g_build_filename (g_get_tmp_dir (), data->name, NULL);
|
||||
unlink (filename);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
#elif defined(G_OS_WIN32)
|
||||
|
||||
@ -689,7 +716,7 @@ _gdk_broadway_server_create_surface (int width,
|
||||
|
||||
data = g_new (BroadwayShmSurfaceData, 1);
|
||||
data->data_size = width * height * sizeof (guint32);
|
||||
data->data = create_random_shm (data->name, data->data_size);
|
||||
data->data = create_random_shm (data->name, data->data_size, &data->is_shm);
|
||||
|
||||
surface = cairo_image_surface_create_for_data ((guchar *)data->data,
|
||||
CAIRO_FORMAT_ARGB32, width, height, width * sizeof (guint32));
|
||||
|
||||
Reference in New Issue
Block a user