diff options
author | Alexander Larsson <alexl@redhat.com> | 2015-06-25 21:15:46 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2015-06-26 00:21:27 +0200 |
commit | da395606a2afcebe9721277295ba14cd86f90fef (patch) | |
tree | d82cac43ea3c15fb0f7096e369dbaf71aae82195 /gdk/broadway | |
parent | 029800c426ef29ad6170e28624b5c4a0a6947cc8 (diff) | |
download | gtk+-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.
Diffstat (limited to 'gdk/broadway')
-rw-r--r-- | gdk/broadway/broadway-server.c | 18 | ||||
-rw-r--r-- | gdk/broadway/gdkbroadway-server.c | 45 |
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)); |