[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#617653:



same Problem here with version 2:1.10.1-2 of xserver-xorg-core.

Looking at the code:

The routine DRI2DrawablePtr is obviously designed to return NULL in certain 
cases (At least if type is UNDRAWABLE_WINDOW). If this is supposed to be 
valid, it should be handled gracefully in DRI2WaitSwap, maybe like in the 
previous post. If not, it should error out right there and make the 
Application fail instead of crashing the xserver.

Looking at the coredump:

Since the 'hot' Varible pDrawable is optimized out, I tried to reconstruct it 
from the underlying stack frames:
From __glXForceCurrent I got
(gdb) p *(cx->drawPriv->pDraw)
$9 = {type = 0 '\000', class = 1 '\001', depth = 24 '\030', bitsPerPixel = 32 
' ', id = 181, x = 0, y = 0, width = 1920, height = 1080, pScreen = 0xf61370, 
serialNumber = 15909060}
and
(gdb) p *((WindowPtr)cx->drawPriv->pDraw)
$10 = {drawable = {type = 0 '\000', class = 1 '\001', depth = 24 '\030', 
bitsPerPixel = 32 ' ', id = 181, x = 0, y = 0, width = 1920, height = 1080, 
pScreen = 0xf61370, serialNumber = 15909060}, devPrivates = 0x12943f0, parent 
= 0x0, nextSib = 0x0, prevSib = 0x0, 
  firstChild = 0x5e97a70, lastChild = 0x3dff8e0, clipList = {extents = {x1 = 
0, y1 = 0, x2 = 0, y2 = 0}, data = 0x7e1a80}, borderClip = {extents = {x1 = 0, 
y1 = 0, x2 = 1920, y2 = 1080}, data = 0x0}, valdata = 0x0, winSize = {extents 
= {x1 = 0, y1 = 0, x2 = 1920, 
      y2 = 1080}, data = 0x0}, borderSize = {extents = {x1 = 0, y1 = 0, x2 = 
1920, y2 = 1080}, data = 0x0}, origin = {x = 0, y = 0}, borderWidth = 0, 
deliverableEvents = 49201, eventMask = 0, background = {pixmap = 0x0, pixel = 
0}, border = {pixmap = 0x0, pixel = 0}, 
  backStorage = 0x0, optional = 0x1294440, backgroundState = 2, borderIsPixel 
= 1, cursorIsNone = 0, backingStore = 0, saveUnder = 0, DIXsaveUnder = 0, 
bitGravity = 1, winGravity = 1, overrideRedirect = 0, visibility = 3, mapped = 
1, realized = 1, viewable = 1, 
  dontPropagate = 0, forcedBS = 0, redirectDraw = 0, forcedBG = 0, 
damagedDescendants = 0}
This brings me to the conclusion, that pDrawable is of type DRAWABLE_WINDOW 
and the NULL-pointer is in fact passed on from dixLookupPrivate to 
DRI2WaitSwap.
This in turn may have something to do with dri2WindowPrivateKey
(gdb) p dri2WindowPrivateKeyRec
$18 = {offset = 0, size = 0, initialized = 1, allocated = 0, type = 
PRIVATE_WINDOW, next = 0x0}
which looks like an empty list to me.
The deeply nestet logic of dixLookupPrivate shows that in this case 
dixGetPrivate dereferences the privates pointer before returning which seems 
to be the origin of the NULL-pointer:
(gdb) x/16a (*((WindowPtr)cx->drawPriv->pDraw))->devPrivates
0x12943f0:      0x0     0x1292b60
0x1294400:      0x4342920       0x0
0x1294410:      0x0     0x0
0x1294420:      0x0     0x5a7bf30
0x1294430:      0x0     0x71
0x1294440:      0x2733240       0x2000000021
0x1294450:      0xfac03100000000        0x3b75c00
0x1294460:      0x43fefa0       0x42f9840
By the way, at offset 1 there seems to be a valid address (might be a 
coincidence).
Anyone out there who can make sense out of this?

Kind regards,
Matthias

Below is a summary of the routines i talked about:

static DRI2DrawablePtr
DRI2GetDrawable(DrawablePtr pDraw)
{
    WindowPtr pWin;
    PixmapPtr pPixmap;
	    switch (pDraw->type) {
    case DRAWABLE_WINDOW:
        pWin = (WindowPtr) pDraw;
        return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
    case DRAWABLE_PIXMAP:
        pPixmap = (PixmapPtr) pDraw;
        return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
    default:
        return NULL;
    }
}

Bool
DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
{
    DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);

    /* If we're currently waiting for a swap on this drawable, reset
     * the request and suspend the client.  We only support one
     * blocked client per drawable. */
    if ((pPriv->swapsPending) &&
        pPriv->blockedClient == NULL) {
        ResetCurrentRequest(client);
        client->sequence--;
        __DRI2BlockClient(client, pPriv);
        return TRUE;
    }

    return FALSE;
}

static inline pointer
dixLookupPrivate(PrivatePtr *privates, const DevPrivateKey key)
{
    if (key->size)
        return dixGetPrivateAddr(privates, key);
    else
        return dixGetPrivate(privates, key);
}

static inline void *
dixGetPrivateAddr(PrivatePtr *privates, const DevPrivateKey key)
{
    assert(key->initialized);
    return (char *) (*privates) + key->offset;
}

static inline void *
dixGetPrivate(PrivatePtr *privates, const DevPrivateKey key)
{
    assert (key->size == 0);
    return *(void **) dixGetPrivateAddr(privates, key);
}



Reply to: