[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