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:
Alexander Larsson
2015-06-25 21:15:46 +02:00
parent 029800c426
commit da395606a2
2 changed files with 51 additions and 12 deletions

View File

@ -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;

View File

@ -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));