[Spice-commits] 3 commits - client/x11

Alexander Larsson alexl at kemper.freedesktop.org
Wed Aug 25 03:35:38 PDT 2010


 client/x11/platform.cpp |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

New commits:
commit 2df2b3df1e9f701f3f4d2d04ea48f5d66de63075
Author: Alexander Larsson <alexl at redhat.com>
Date:   Wed Aug 25 12:15:17 2010 +0200

    client: Handle async errors from xshm setup
    
    XShmAttach can fail asynchronously, so we need to check the
    errors in the x error handler during the XSync.

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index f80f0dc..8292d44 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -109,6 +109,8 @@ static Atom utf8_atom;
 #ifdef USE_XRANDR_1_2
 static bool clipboard_inited = false;
 #endif
+static Bool handle_x_error = false;
+static int x_error_code;
 
 class DefaultEventListener: public Platform::EventListener {
 public:
@@ -219,6 +221,18 @@ Display* XPlatform::get_display()
     return x_display;
 }
 
+static void handle_x_errors_start(void)
+{
+    handle_x_error = True;
+    x_error_code = 0;
+}
+
+static int handle_x_errors_stop(void)
+{
+    handle_x_error = False;
+    return x_error_code;
+}
+
 bool XPlatform::is_x_shm_avail()
 {
     return x_shm_avail;
@@ -277,9 +291,16 @@ XImage *XPlatform::create_x_shm_image(RedDrawable::Format format,
         goto err2;
     }
 
+    handle_x_errors_start();
+
     /* Ensure the xserver has attached the xshm segment */
     XSync (XPlatform::get_display(), False);
 
+    if (handle_x_errors_stop()) {
+        x_shm_avail = false;
+        goto err2;
+    }
+
     /* Mark segment as released so that it will be destroyed when
        the xserver releases the segment. This way we won't leak
        the segment if the client crashes. */
@@ -2493,6 +2514,13 @@ static int x_error_handler(Display* display, XErrorEvent* error_event)
     char request_str[256];
     char number_str[32];
 
+    if (handle_x_error) {
+        if (error_event->error_code) {
+            x_error_code = error_event->error_code;
+        }
+        return 0;
+    }
+
     char* display_name = XDisplayString(display);
     XGetErrorText(display, error_event->error_code, error_str, sizeof(error_str));
 
commit 7c7e3efff31a8c225bb7029d08675aa617635a95
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Aug 23 17:11:39 2010 +0200

    client: Don't leak xshm segments

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index 1b54bc3..f80f0dc 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -277,6 +277,14 @@ XImage *XPlatform::create_x_shm_image(RedDrawable::Format format,
         goto err2;
     }
 
+    /* Ensure the xserver has attached the xshm segment */
+    XSync (XPlatform::get_display(), False);
+
+    /* Mark segment as released so that it will be destroyed when
+       the xserver releases the segment. This way we won't leak
+       the segment if the client crashes. */
+    shmctl(shminfo->shmid, IPC_RMID, 0);
+
     image->data = (char *)shminfo->shmaddr;
 
     *shminfo_out = shminfo;
commit 7c61dfee893da1ea1ee48aa8590ffb52afa573b8
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Aug 23 16:57:50 2010 +0200

    Don't try xshm any more if it fails for a permanent reason
    
    This is copied from how Gtk+ detects Xshm failures.

diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index 3b9f4af..1b54bc3 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -242,22 +242,38 @@ XImage *XPlatform::create_x_shm_image(RedDrawable::Format format,
                             format == RedDrawable::A1 ? XYBitmap : ZPixmap,
                             NULL, shminfo, width, height);
     if (image == NULL) {
+	x_shm_avail = false;
         goto err1;
     }
 
     shminfo->shmid = shmget(IPC_PRIVATE, height * image->bytes_per_line,
                             IPC_CREAT | 0777);
     if (shminfo->shmid < 0) {
+        /* EINVAL indicates, most likely, that the segment we asked for
+         * is bigger than SHMMAX, so we don't treat it as a permanent
+         * error. ENOSPC and ENOMEM may also indicate this, but
+         * more likely are permanent errors.
+         */
+        if (errno != EINVAL) {
+            x_shm_avail = false;
+        }
         goto err2;
     }
 
     shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
     if (!shminfo->shmaddr) {
+        /* Failure in shmat is almost certainly permanent. Most likely error is
+         * EMFILE, which would mean that we've exceeded the per-process
+         * Shm segment limit.
+         */
+        x_shm_avail = false;
+
         goto err2;
     }
 
     shminfo->readOnly = False;
     if (!XShmAttach(XPlatform::get_display(), shminfo)) {
+        x_shm_avail = false;
         goto err2;
     }
 


More information about the Spice-commits mailing list