[PATCH xserver] Fix race condition in ConfigureWindow

Erik Kurzinger ekurzinger at nvidia.com
Wed Oct 26 21:16:11 UTC 2016


Currently, the ConfigureWindow function will deliver a ConfigureNotify
event to the application before calling into the window's appropriate
function with the new size / position.  Hence, the application may
begin to process the event before some server-size data structures are
updated with the new information leading to a potentially inconsistent
state.

The issue has been causing problems with our OpenGL driver,
specifically when something like the following sequence of events
happens after a window resize:
1. [xserver]     send ConfigureNotify event to application
2. [application] call into client-side OpenGL code in response to resize
3. [driver]      read shared memory variable (call it x) indicating 
whether
                  current window has been resized, see that it has not,
 	         proceed without updating client side data structures
4. [xserver]     call pScreen->ResizeWindow(...), eventually calling into
                  server-side OpenGL code
5. [driver]      update server side data structures, and write to x
                  indicating that the window has changed

(2 -> 3) and (4 -> 5) occur asynchronously.  If they run in the order
described above, it can leave the client side and server side driver
components to disagree, causing problems later on.

This change will ensure the new configuration is fully processed by the
server before any event is sent to the application.

Signed-off-by: Erik Kurzinger <ekurzinger at nvidia.com>
---
  dix/window.c | 50 ++++++++++++++++++++++++++------------------------
  1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/dix/window.c b/dix/window.c
index ead4dc2..7177ae3 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -2368,6 +2368,32 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID 
*vlist, ClientPtr client)
      return Success;

   ActuallyDoSomething:
+    if (mask & CWBorderWidth) {
+        if (action == RESTACK_WIN) {
+            action = MOVE_WIN;
+            pWin->borderWidth = bw;
+        }
+        else if ((action == MOVE_WIN) &&
+                 (beforeX + wBorderWidth(pWin) == x + (int) bw) &&
+                 (beforeY + wBorderWidth(pWin) == y + (int) bw)) {
+            action = REBORDER_WIN;
+            (*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
+        }
+        else
+            pWin->borderWidth = bw;
+    }
+    if (action == MOVE_WIN)
+        (*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
+                                               (mask & CWBorderWidth) ? 
VTOther
+                                               : VTMove);
+    else if (action == RESIZE_WIN)
+        (*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
+    else if (mask & CWStackMode)
+        ReflectStackChange(pWin, pSib, VTOther);
+
+    if (action != RESTACK_WIN)
+        CheckCursorConfinement(pWin);
+
      if (pWin->drawable.pScreen->ConfigNotify) {
          int ret;

@@ -2400,31 +2426,7 @@ ConfigureWindow(WindowPtr pWin, Mask mask, XID 
*vlist, ClientPtr client)
  #endif
          DeliverEvents(pWin, &event, 1, NullWindow);
      }
-    if (mask & CWBorderWidth) {
-        if (action == RESTACK_WIN) {
-            action = MOVE_WIN;
-            pWin->borderWidth = bw;
-        }
-        else if ((action == MOVE_WIN) &&
-                 (beforeX + wBorderWidth(pWin) == x + (int) bw) &&
-                 (beforeY + wBorderWidth(pWin) == y + (int) bw)) {
-            action = REBORDER_WIN;
-            (*pWin->drawable.pScreen->ChangeBorderWidth) (pWin, bw);
-        }
-        else
-            pWin->borderWidth = bw;
-    }
-    if (action == MOVE_WIN)
-        (*pWin->drawable.pScreen->MoveWindow) (pWin, x, y, pSib,
-                                               (mask & CWBorderWidth) ? 
VTOther
-                                               : VTMove);
-    else if (action == RESIZE_WIN)
-        (*pWin->drawable.pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
-    else if (mask & CWStackMode)
-        ReflectStackChange(pWin, pSib, VTOther);

-    if (action != RESTACK_WIN)
-        CheckCursorConfinement(pWin);
      return Success;
  #undef RESTACK_WIN
  #undef MOVE_WIN
-- 
2.7.4




More information about the xorg-devel mailing list