/** Free the previously allocated Glyph Sets for each screen. */ static int dmxProcRenderFreeGlyphSet(ClientPtr client) { GlyphSetPtr glyphSet; REQUEST(xRenderFreeGlyphSetReq); REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); dixLookupResourceByType((pointer *) &glyphSet, stuff->glyphset, GlyphSetType, client, DixDestroyAccess); if (glyphSet && glyphSet->refcnt == 1) { dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); int i; for (i = 0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; if (dmxScreen->beDisplay) { if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet)) dmxSync(dmxScreen, FALSE); } } MAXSCREENSFREE(glyphPriv->glyphSets); free(glyphPriv); DMX_SET_GLYPH_PRIV(glyphSet, NULL); } return dmxSaveRenderVector[stuff->renderReqType] (client); }
/** Unrealize the font, \a pFont, on the back-end server associated with * \a pScreen. */ Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) { DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; dmxFontPrivPtr pFontPriv; if ((pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { /* In case the font failed to load properly */ if (!pFontPriv->refcnt) { MAXSCREENSFREE(pFontPriv->font); free(pFontPriv); FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); } else if (pFontPriv->font[pScreen->myNum]) { if (dmxScreen->beDisplay) dmxBEFreeFont(pScreen, pFont); /* The code below is non-obvious, so here's an explanation... * * When creating the default GC, the server opens up the * default font once for each screen, which in turn calls * the RealizeFont function pointer once for each screen. * During this process both dix's font refcnt and DMX's font * refcnt are incremented once for each screen. * * Later, when shutting down the X server, dix shuts down * each screen in reverse order. During this shutdown * procedure, each screen's default GC is freed and then * that screen is closed by calling the CloseScreen function * pointer. screenInfo.numScreens is then decremented after * closing each screen. This procedure means that the dix's * font refcnt for the font used by the default GC's is * decremented once for each screen # greater than 0. * However, since dix's refcnt for the default font is not * yet 0 for each screen greater than 0, no call to the * UnrealizeFont function pointer is made for those screens. * Then, when screen 0 is being closed, dix's font refcnt * for the default GC's font is finally 0 and the font is * unrealized. However, since screenInfo.numScreens has * been decremented already down to 1, only one call to * UnrealizeFont is made (for screen 0). Thus, even though * RealizeFont was called once for each screen, * UnrealizeFont is only called for screen 0. * * This is a bug in dix. * * To avoid the memory leak of pFontPriv for each server * generation, we can also free pFontPriv if the refcnt is * not yet 0 but the # of screens is 1 -- i.e., the case * described in the dix bug above. This is only a temporary * workaround until the bug in dix is solved. * * The other problem is that the font structure allocated by * XLoadQueryFont() above is not freed for screens > 0. * This problem cannot be worked around here since the back- * end displays for screens > 0 have already been closed by * the time this code is called from dix. * * When the bug in dix described above is fixed, then we can * remove the "|| screenInfo.numScreens == 1" code below and * the memory leaks will be eliminated. */ if (--pFontPriv->refcnt == 0 #if 1 /* Remove this code when the dix bug is fixed */ || screenInfo.numScreens == 1 #endif ) { MAXSCREENSFREE(pFontPriv->font); free(pFontPriv); FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); } } } return TRUE; }