[gtk+] broadway: Handle shm_open failing by falling back on tmp files



commit da395606a2afcebe9721277295ba14cd86f90fef
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Jun 25 21:15:46 2015 +0200

    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.

 gdk/broadway/broadway-server.c    |   18 ++++++++++++--
 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 547729f..9c484b6 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 40f1ca7..acfb2de 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));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]