[PATCH v2 08/10] dri2: Send events only to known clients

Pauli Nieminen ext-pauli.nieminen at nokia.com
Mon Feb 14 23:18:36 PST 2011


On 14/02/11 21:06 +0200, Ville Syrjälä wrote:
> On Tue, Feb 08, 2011 at 11:42:54PM +0200, ext Pauli wrote:
> > From: Pauli Nieminen <ext-pauli.nieminen at nokia.com>
> > 
> > If client disconnects and new client gets same id DRI2 events may end to
> > wrong client. DRI2 reference list can be checked to see if the client
> > still owns the DRI2Drawable.
> > 
> > Signed-off-by: Pauli Nieminen <ext-pauli.nieminen at nokia.com>
> > ---
> >  hw/xfree86/dri2/dri2.c |   73 +++++++++++++++++++++++++++++++++++------------
> >  1 files changed, 54 insertions(+), 19 deletions(-)
> > 
> > diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
> > index 9133bb3..c77ac9b 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 *
> > @@ -266,7 +270,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;
> > @@ -753,28 +758,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
> > @@ -816,7 +834,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);
> > @@ -828,9 +846,10 @@ 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;
> > +    DRI2DrawableRefPtr      ref;
> >  
> >      pPriv->swapsPending--;
> >      pPriv->swap_count++;
> > @@ -841,6 +860,11 @@ DRI2SwapComplete2(DRI2DrawablePtr pPriv, int frame,
> >      if (client == NULL)
> >  	goto out;
> >  
> > +    ref = DRI2LookupClientDrawableRef(pPriv, client, 0);
> > +
> > +    if (ref == NULL)
> > +	goto out;
> 
> This bit escapes me. pSwapData->event.client is not NULL, so we know
> the original client is still around. Are we now assuming that
> DRI2SwapComplete2 was somehow called with an incorrect pSwapData
> since we have to go looking for the client's ID in the ref list?
> 

We still have to check that client haven't called DRIDestroyDrawable. In that
case client shouldn't receive "random" DRI2 events.

> > +
> >      if (pDraw) {
> >  	BoxRec          box;
> >  	RegionRec       region;
> > @@ -934,9 +958,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) {
> > @@ -1062,13 +1086,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 */
> > @@ -1081,6 +1114,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;
> >      }
> >  
> > @@ -1316,7 +1351,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 at lists.x.org: X.Org development
> > Archives: http://lists.x.org/archives/xorg-devel
> > Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 
> -- 
> Ville Syrjälä


More information about the xorg-devel mailing list