From: Pauli Nieminen <ext-pauli.niemi...@nokia.com>

If client disconnects and new client gets same id DRI2MSC replies may end to
wrong client. Client state can be tracked to check if event reply should
be send when hw event happens.

Signed-off-by: Pauli Nieminen <ext-pauli.niemi...@nokia.com>
---
 hw/xfree86/dri2/dri2.c |   67 ++++++++++++++++++++++++++++++++++-------------
 1 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 21a89e4..28b72f5 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -111,12 +111,16 @@ typedef struct _DRI2Screen {
     ConfigNotifyProcPtr                 ConfigNotify;
 } DRI2ScreenRec;
 
+typedef struct _DRI2ClientEventRec {
+    ClientPtr          client;
+    struct list                link;
+} DRI2ClientEventRec, *DRI2ClientEventPtr;
+
 typedef struct _DRI2SwapCompleteDataRec {
     DRI2BufferPtr      src;
     DRI2BufferPtr      dest;
-    ClientPtr          client;
     void *             data;
-    struct list                link;
+    DRI2ClientEventRec event;
 } DRI2SwapCompleteDataRec, *DRI2SwapCompleteDataPtr;
 
 static struct list *
@@ -273,7 +277,8 @@ DRI2LookupClientDrawableRef(DRI2DrawablePtr pPriv, 
ClientPtr client, XID id)
     DRI2DrawableRefPtr ref;
 
     list_for_each_entry(ref, &pPriv->reference_list, link) {
-       if (CLIENT_ID(ref->dri2_id) == client->index && ref->id == id)
+       if (CLIENT_ID(ref->dri2_id) == client->index &&
+               (id == 0 || ref->id == id))
            return ref;
     }
     return NULL;
@@ -760,28 +765,41 @@ DRI2CanExchange(DrawablePtr pDraw)
     return FALSE;
 }
 
+static void
+cleanup_client_event(DRI2ClientEventPtr event)
+{
+    if (event->client)
+       list_del(&event->link);
+}
+
 void
 DRI2WaitMSCComplete2(DRI2DrawablePtr pPriv, int frame,
                     unsigned int tv_sec, unsigned int tv_usec,
                     void *data)
 {
-    ClientPtr client = data;
+    ClientPtr          blockedClient = pPriv->blockedClient;
+    DRI2ClientEventPtr pEvent = data;
+    ClientPtr          client = pEvent->client;
 
+    pPriv->blockedClient = NULL;
+    pPriv->blockedOnMsc = FALSE;
     pPriv->refcnt--;
 
-    if (pPriv->refcnt <= 0) {
-       DRI2DrawableGone(pPriv, 0);
-       return;
-    }
+    if (client == NULL)
+       goto out;
 
     ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
                         frame, pPriv->swap_count);
 
-    if (pPriv->blockedClient)
-       AttendClient(pPriv->blockedClient);
+    if (blockedClient)
+       AttendClient(blockedClient);
 
-    pPriv->blockedClient = NULL;
-    pPriv->blockedOnMsc = FALSE;
+out:
+    cleanup_client_event(pEvent);
+    free(pEvent);
+
+    if (pPriv->refcnt <= 0)
+       DRI2DrawableGone(pPriv, 0);
 }
 
 static void
@@ -823,7 +841,7 @@ DRI2WakeClient(ClientPtr client, DRI2DrawablePtr pPriv, int 
frame,
 static void
 free_swap_complete_data (DRI2DrawablePtr pPriv, DRI2SwapCompleteDataPtr 
pSwapData)
 {
-    list_del(&pSwapData->link);
+    cleanup_client_event(&pSwapData->event);
     buffer_unref(pPriv, pSwapData->src);
     buffer_unref(pPriv, pSwapData->dest);
     free(pSwapData);
@@ -835,7 +853,7 @@ DRI2SwapComplete2(DRI2DrawablePtr pPriv, int frame,
                   DRI2SwapEventPtr swap_complete, void *swap_data)
 {
     DRI2SwapCompleteDataPtr pSwapData = swap_data;
-    ClientPtr               client = pSwapData->client;
+    ClientPtr               client = pSwapData->event.client;
     DrawablePtr             pDraw = pPriv->drawable;
     CARD64                  ust = 0;
 
@@ -941,9 +959,9 @@ DRI2SwapBuffers(ClientPtr client, DRI2DrawablePtr pPriv, 
CARD64 target_msc,
     buffer_ref(pDestBuffer);
     pSwapData->src = pSrcBuffer;
     pSwapData->dest = pDestBuffer;
-    pSwapData->client = client;
     pSwapData->data = data;
-    list_add (&pSwapData->link, clientEvents);
+    pSwapData->event.client = client;
+    list_add (&pSwapData->event.link, clientEvents);
 
     /* Old DDX or no swap interval, just blit */
     if (!ds->ScheduleSwap || !pPriv->swap_interval) {
@@ -1069,13 +1087,22 @@ int
 DRI2WaitMSC(ClientPtr client, DRI2DrawablePtr pPriv, CARD64 target_msc,
            CARD64 divisor, CARD64 remainder)
 {
-    DRI2ScreenPtr ds = pPriv->dri2_screen;
-    DrawablePtr   pDraw = pPriv->drawable;
+    DRI2ScreenPtr      ds = pPriv->dri2_screen;
+    DrawablePtr        pDraw = pPriv->drawable;
+    struct list *      clientEvents = DRI2GetClientEventList(client);
+    DRI2ClientEventPtr pEvent;
     Bool ret;
 
     if (pDraw == NULL)
        return BadDrawable;
 
+    pEvent = malloc(sizeof *pEvent);
+    if (!pEvent)
+       return BadAlloc;
+
+    pEvent->client = client;
+    list_add(&pEvent->link, clientEvents);
+
     pPriv->refcnt++;
 
     /* Old DDX just completes immediately */
@@ -1088,6 +1115,8 @@ DRI2WaitMSC(ClientPtr client, DRI2DrawablePtr pPriv, 
CARD64 target_msc,
     ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, 
remainder, client);
     if (!ret) {
        pPriv->refcnt--;
+       cleanup_client_event(pEvent);
+       free(pEvent);
        return BadDrawable;
     }
 
@@ -1323,7 +1352,7 @@ DRI2ClientCallback(CallbackListPtr *ClientStateCallback, 
pointer closure, pointe
     NewClientInfoRec *clientinfo = calldata;
     ClientPtr pClient = clientinfo->client;
     struct list *clientEvents = DRI2GetClientEventList(pClient);
-    DRI2SwapCompleteDataPtr ref, next;
+    DRI2ClientEventPtr ref, next;
 
     switch (pClient->clientState) {
        case ClientStateInitial:
-- 
1.7.0.4

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to