]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
[tools-plugin] Potential solution for reported desktopEvent crash
authorOliver Kurth <okurth@vmware.com>
Fri, 6 Jul 2018 21:31:55 +0000 (14:31 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 6 Jul 2018 21:31:55 +0000 (14:31 -0700)
On several distros like RHEL, CentOS and Fedora, plugin desktopEvents.so
crashes have been reported.  However, neither development or QE can
reproduce this issue in local environments.

The XFetchName document states that it may generate BadWindow error.  That
means that the value for a Window argument does not name a defined Window.
X FAQ also suggests handling badwindow error after finding it.  Since
the window does not exist when XFetchName is run on it, the name is not
needed.  Suppress this error to avoid a crash.

After grabbing the X server, use XSetErrorHandler to temporarily define
a local error handler to intercept and cleanly handle any BadWindow
errors.  XSetErrorHandler returns the current error handler, so it is
straightforward to reinstate GDK's original handler.

open-vm-tools/services/plugins/desktopEvents/x11Lock.c

index 613b69463fc47502bf96ebfe802998366f1b480c..811f4bf7eef6905ef5b6e15c4a0b5dcd584ccdf0 100644 (file)
@@ -161,6 +161,43 @@ QueryX11Lock(Display *dpy,
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * FetchNameErrorHandler --
+ *
+ *      According to XFetchName document, XFetchName may generate a BadWindow
+ *      error. In this case, the pointer we pass to XFetchName doesn't name a
+ *      defined window. X is asynchronous, there isn't a gurantee that the
+ *      window is still alive between the time the window is obtained and
+ *      the time a event is sent to the window. So, for this scenario, since
+ *      the window doesn't exist, we can ignore checking its name. This can
+ *      avoid this plugin from crashing. Refer to PR 1871141 for details.
+ *
+ * Results:
+ *      Logs error.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+FetchNameErrorHandler(Display *display,
+                      XErrorEvent *error)
+{
+   /* 256 is enough for the error description. */
+   char msg[256];
+   XGetErrorText(display, error->error_code, msg, sizeof(msg));
+
+   g_warning("X Error %d (%s): request %d.%d\n",
+             error->error_code, msg, error->request_code, error->minor_code);
+
+   return 0;
+}
+
+
 /*
  ******************************************************************************
  * AcquireDisplayLock --                                                */ /**
@@ -281,15 +318,24 @@ AcquireDisplayLock(void)
     */
    for (index = 0; (index < nchildren) && !alreadyLocked; index++) {
       char *name = NULL;
+      /* Use customized error handler to suppress BadWindow error. */
+      int (*oldXErrorHandler)(Display*, XErrorEvent*) =
+         XSetErrorHandler(FetchNameErrorHandler);
 
       /* Skip unless window is named vmware-user. */
       if ((XFetchName(defaultDisplay, children[index], &name) == 0) ||
           (name == NULL) ||
           strcmp(name, VMUSER_TITLE)) {
          XFree(name);
+
+         /* Restore default error handler. */
+         XSetErrorHandler(oldXErrorHandler);
          continue;
       }
 
+      /* Restore default error handler. */
+      XSetErrorHandler(oldXErrorHandler);
+
       /*
        * Query the window for the "vmware-user-lock" property.
        */