[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