From 711e26466ae04ae93ff4c48d377d83d68a6320e9 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 25 Jan 2010 09:21:51 -0800 Subject: DRI2: handle drawable destruction properly at DRI2SwapComplete time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simon reported an issue with kwin that turned out to be a general problem. If a drawable goes away before its swap completes, we'll try to free it up. However, we free it improperly, which causes a server crash in DRI2DestroyDrawable. Fix that up by splitting the free code out and calling it from DRI2SwapComplete. Signed-off-by: Jesse Barnes Reviewed-by: Michel Dänzer Signed-off-by: Keith Packard --- hw/xfree86/dri2/dri2.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 3d0fa75ec..587a9285a 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -158,6 +158,31 @@ DRI2CreateDrawable(DrawablePtr pDraw) return Success; } +static void +DRI2FreeDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv; + WindowPtr pWin; + PixmapPtr pPixmap; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return; + + xfree(pPriv); + + if (pDraw->type == DRAWABLE_WINDOW) + { + pWin = (WindowPtr) pDraw; + dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); + } + else + { + pPixmap = (PixmapPtr) pDraw; + dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); + } +} + static int find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) { @@ -508,7 +533,7 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, if (pPriv->refCount == 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[DRI2] %s: bad drawable refcount\n", __func__); - xfree(pPriv); + DRI2FreeDrawable(pDraw); return; } @@ -729,8 +754,6 @@ DRI2DestroyDrawable(DrawablePtr pDraw) { DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); DRI2DrawablePtr pPriv; - WindowPtr pWin; - PixmapPtr pPixmap; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) @@ -753,18 +776,7 @@ DRI2DestroyDrawable(DrawablePtr pDraw) * actually free the priv yet. We'll need it in the DRI2SwapComplete() * callback and we'll free it there once we're done. */ if (!pPriv->swapsPending) - xfree(pPriv); - - if (pDraw->type == DRAWABLE_WINDOW) - { - pWin = (WindowPtr) pDraw; - dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); - } - else - { - pPixmap = (PixmapPtr) pDraw; - dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); - } + DRI2FreeDrawable(pDraw); } Bool -- cgit v1.2.3