[RFC xserver] xwayland: HACK: Don't roundtrip in DRI2 authentication mechanism

Tiago Vignatti tiago.vignatti at intel.com
Tue Jan 22 14:19:12 PST 2013


Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
 hw/xfree86/dri2/dri2.c             |   60 ++++++++++++++++++++++++++++++++++--
 hw/xfree86/dri2/dri2.h             |    8 ++++-
 hw/xfree86/dri2/dri2ext.c          |   10 +++++-
 hw/xfree86/xwayland/xwayland-drm.c |   22 +++++++++----
 4 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index b08618a..a529d5e 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -99,6 +99,7 @@ typedef struct _DRI2Screen {
     const char *deviceName;
     int fd;
     unsigned int lastSequence;
+    ClientPtr blockedAuthClient;
 
     DRI2CreateBufferProcPtr CreateBuffer;
     DRI2DestroyBufferProcPtr DestroyBuffer;
@@ -1122,13 +1123,65 @@ DRI2AuthMagic (ScreenPtr pScreen, uint32_t magic)
     return (*ds->LegacyAuthMagic) (ds->fd, magic);
 }
 
+/*
+ * Return TRUE if it has a blocked client waiting authentication or
+ * FALSE otherwise.
+ */
 Bool
-DRI2Authenticate(ScreenPtr pScreen, uint32_t magic)
+DRI2HasBlockedAuthClient(ScreenPtr pScreen)
 {
     DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
 
-    if (ds == NULL || (*ds->AuthMagic) (pScreen, magic))
-        return FALSE;
+    if (ds == NULL)
+	return FALSE;
+
+    if (!ds->blockedAuthClient)
+	return FALSE;
+    else
+	return TRUE;
+}
+
+/*
+ * Attend blocked client that was asking for authentication. In other words,
+ * it will process the DRI2Authenticate request again.
+ *
+ * This has to be called only if the client has been in fact authenticated by
+ * DRM, meaning the token magic was accepted.
+ */
+void
+DRI2AttendBlockedAuthClient(ScreenPtr pScreen)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+    if (ds == NULL || !DRI2HasBlockedAuthClient(pScreen))
+	return;
+
+    AttendClient(ds->blockedAuthClient);
+}
+
+Bool
+DRI2Authenticate(ScreenPtr pScreen, uint32_t magic, ClientPtr client)
+{
+    DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+
+    fprintf(stderr, "%s (blocked client: %p)\n", __func__, ds->blockedAuthClient);
+    if (ds == NULL)
+	return FALSE;
+
+    if (DRI2HasBlockedAuthClient(pScreen) &&
+	ds->blockedAuthClient == client) {
+	ds->blockedAuthClient = NULL;
+	return TRUE;
+    }
+
+    /* XXX: this assumes magic will never fail */
+    if ((*ds->AuthMagic) (pScreen, magic)) {
+	ResetCurrentRequest(client);
+	client->sequence--;
+	IgnoreClient(client);
+	ds->blockedAuthClient = client;
+	return FALSE;
+    }
 
     return TRUE;
 }
@@ -1198,6 +1251,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     ds->screen = pScreen;
     ds->fd = info->fd;
     ds->deviceName = info->deviceName;
+    ds->blockedAuthClient = NULL;
     dri2_major = 1;
 
     ds->CreateBuffer = info->CreateBuffer;
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index cec9634..195a253 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -238,7 +238,13 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
                                   const char **driverName,
                                   const char **deviceName);
 
-extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, uint32_t magic);
+extern _X_EXPORT Bool DRI2HasBlockedAuthClient(ScreenPtr pScreen);
+
+extern _X_EXPORT void DRI2AttendBlockedAuthClient(ScreenPtr pScreen);
+
+extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen,
+				       uint32_t magic,
+				       ClientPtr client);
 
 extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
                                         DrawablePtr pDraw,
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 2579a5c..9f1cf0f 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -149,8 +149,16 @@ ProcDRI2Authenticate(ClientPtr client)
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
-    rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic);
+
+    status = DRI2Authenticate(pDraw->pScreen, stuff->magic, client);
+    if (status != TRUE && DRI2HasBlockedAuthClient(pDraw->pScreen)) {
+	fprintf(stderr, "%s: client BLOCKED\n", __func__);
+	return Success;
+    }
+
+    rep.authenticated = status;
     WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);
+    fprintf(stderr, "%s: wrote back to client\n", __func__);
 
     return Success;
 }
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
index c19eb84..4ca143d 100644
--- a/hw/xfree86/xwayland/xwayland-drm.c
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -45,6 +45,7 @@
 
 #include "xwayland.h"
 #include "xwayland-private.h"
+#include "../dri2/dri2.h"
 
 static void
 drm_handle_device (void *data, struct wl_drm *drm, const char *device)
@@ -64,7 +65,13 @@ drm_handle_authenticated (void *data, struct wl_drm *drm)
 {
     struct xwl_screen *xwl_screen = data;
 
+    fprintf(stderr, "%s\n", __func__);
     xwl_screen->authenticated = 1;
+
+    if (!xwl_screen->screen)
+	return;
+
+    DRI2AttendBlockedAuthClient(xwl_screen->screen);
 }
 
 static const struct wl_drm_listener xwl_drm_listener =
@@ -146,18 +153,21 @@ int xwl_screen_get_drm_fd(struct xwl_screen *xwl_screen)
 int xwl_drm_authenticate(struct xwl_screen *xwl_screen,
 			    uint32_t magic)
 {
-    int ret;
-
     xwl_screen->authenticated = 0;
 
     if (xwl_screen->drm)
 	wl_drm_authenticate (xwl_screen->drm, magic);
 
-    ret = wl_display_roundtrip(xwl_screen->display);
-    if (ret == -1)
-	return BadAlloc;
+    /* at this point we would need to force a roundtrip to guarantee the
+     * client is authenticated by the compositor (xwl_screen->authenticated ==
+     * 1). But, assuming the WM is in the same process of Wayland compositor,
+     * this roundtrip cannot be performed because it might result in a
+     * deadlock state, for the case the WM is waiting for a reply on X server.
+     * Thus, the X server needs to return to the main loop, serve the WM,
+     * block X client and try the same request (DRI2Authenticate) later. */
+
     if (!xwl_screen->authenticated)
-	return BadAlloc;
+	return BadAccess;
 
     return Success;
 }
-- 
1.7.9.5



More information about the wayland-devel mailing list