summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2015-06-25 21:15:46 +0200
committerAlexander Larsson <alexl@redhat.com>2015-06-26 00:21:27 +0200
commitda395606a2afcebe9721277295ba14cd86f90fef (patch)
treed82cac43ea3c15fb0f7096e369dbaf71aae82195
parent029800c426ef29ad6170e28624b5c4a0a6947cc8 (diff)
downloadgtk+-da395606a2afcebe9721277295ba14cd86f90fef.tar.gz
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.
-rw-r--r--gdk/broadway/broadway-server.c18
-rw-r--r--gdk/broadway/gdkbroadway-server.c45
2 files changed, 51 insertions, 12 deletions
diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c
index 547729fa27..9c484b6540 100644
--- a/gdk/broadway/broadway-server.c
+++ b/gdk/broadway/broadway-server.c
@@ -825,19 +825,31 @@ 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");
- return NULL;
+ 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);
- shm_unlink (name);
+ if (filename)
+ {
+ unlink (filename);
+ g_free (filename);
+ }
+ else
+ shm_unlink (name);
return ptr;
diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c
index 40f1ca731f..acfb2dedd5 100644
--- a/gdk/broadway/gdkbroadway-server.c
+++ b/gdk/broadway/gdkbroadway-server.c
@@ -524,10 +524,11 @@ _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;
@@ -535,10 +536,24 @@ map_named_shm (char *name, gsize size)
fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
if (fd == -1)
{
- if (errno != EEXIST)
- g_error ("Unable to allocate shared mem for window");
- return NULL;
+ 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,7 +562,10 @@ map_named_shm (char *name, gsize size)
res = posix_fallocate (fd, 0, size);
if (res != 0 && errno == ENOSPC)
{
- shm_unlink (name);
+ if (filename)
+ unlink (filename);
+ else
+ shm_unlink (name);
g_error ("Not enough shared memory for window surface");
}
#endif
@@ -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);
- shm_unlink (data->name);
+ 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));