mpsuzuki at hiroshima-u.ac.jp
2010-Jan-21 11:27 UTC
[Fontconfig] The reference counter handling in FcConfigGetCurrent() and FcConfigReference().
Dear fontconfig maintainers, FcConfig object includes its reference counter, it prevents that FcConfigDestroy() frees an object in use. I think it''s good design. In the current implementation, I''m questionable about 2 points: P1) FcConfigGetCurrent() does not increment the reference counter when it returns existing FcConfig object. P2) FcConfigReference() increments the reference counter even when it returns new object created by FcConfigGetCurrent(). By P1, some libraries linking other libraries which uses fontconfig too cannot free FcConfig object safely. For example, poppler links fontconfig by itself (to import font resources out of the document), and sometimes it links cairo (to render PDF to scalable graphics) which links fontconfig too. The poppler invokes FcConfigGetCurrent() when it reads given PDF document, and sometimes cairo invoked by poppler invokes FcConfigGetCurrent() again, to write an output file. Unfortunately, the dependency of poppler onto cairo is not essential, so, poppler does not pass FcConfig object to cairo. Also no cairo API takes FcConfig object from the caller. How we can free the object obtained by FcConfigGetCurrent()? In current implementation, we cannot know how many clients invoked FcConfigGetCurrent() from FcConfig->ref, so invoking FcConfigDestroy() is not safe. As a result, poppler does not invoke FcConfigDestroy() at all, although poppler frees an object including the reference to FcConfig obtained by FcConfigGetCurrent(). So, valgrind finds a memory leak in some programs. See recent discussion in poppler mail list: http://lists.freedesktop.org/archives/poppler/2010-January/005429.html http://lists.freedesktop.org/archives/poppler/2010-January/005446.html http://lists.freedesktop.org/archives/poppler/2010-January/005453.html FcConfigReference() looks slightly better about its handling of reference counter. Invoking FcConfigDestroy() for the object obtained by FcConfigReference( NULL ) is safer than the object obtained by FcConfigGetCurrent(). However, by P2, the minimum reference counter of the object obtained by FcConfigGetCurrent( NULL ) is 2, not 1. FcConfigGetCurrent() sets the reference counter to 1, and FcConfigReference() increments it. As a result, - Invoke FcConfigReference( NULL ) once - Invoke FcConfigDestroy( config ) twice is required for real freeing of the FcConfig object. This is not intuitive. In summary, I want to propose following modifications: M1) FcConfigGetCurrent() increments the reference counter when it returns existing object. M2) FcConfigDestroy() does not increment the reference counter when it is invoked with NULL pointer and FcConfigGetCurrent() is invoked. Please give me comment. Regards, mpsuzuki
Behdad Esfahbod
2010-Jan-21 20:32 UTC
[Fontconfig] The reference counter handling in FcConfigGetCurrent() and FcConfigReference().
Hi, What you are observing is simply that fontconfig is caching one instance of FcConfig. That''s by design. If you want that freed, you can call FcFini(). That''s not a *leak*. A leak is memory lost. Forever. behdad On 01/21/2010 06:27 AM, mpsuzuki at hiroshima-u.ac.jp wrote:> Dear fontconfig maintainers, > > FcConfig object includes its reference counter, it prevents > that FcConfigDestroy() frees an object in use. I think it''s > good design. > > In the current implementation, I''m questionable about 2 points: > > P1) FcConfigGetCurrent() does not increment the reference > counter when it returns existing FcConfig object. > > P2) FcConfigReference() increments the reference counter > even when it returns new object created by FcConfigGetCurrent(). > > By P1, some libraries linking other libraries which uses > fontconfig too cannot free FcConfig object safely. > > For example, poppler links fontconfig by itself (to import > font resources out of the document), and sometimes it links > cairo (to render PDF to scalable graphics) which links > fontconfig too. > > The poppler invokes FcConfigGetCurrent() when it reads > given PDF document, and sometimes cairo invoked by poppler > invokes FcConfigGetCurrent() again, to write an output file. > Unfortunately, the dependency of poppler onto cairo is > not essential, so, poppler does not pass FcConfig object > to cairo. Also no cairo API takes FcConfig object from > the caller. > > How we can free the object obtained by FcConfigGetCurrent()? > In current implementation, we cannot know how many clients > invoked FcConfigGetCurrent() from FcConfig->ref, so invoking > FcConfigDestroy() is not safe. As a result, poppler does not > invoke FcConfigDestroy() at all, although poppler frees an > object including the reference to FcConfig obtained by > FcConfigGetCurrent(). So, valgrind finds a memory leak in > some programs. See recent discussion in poppler mail list: > > http://lists.freedesktop.org/archives/poppler/2010-January/005429.html > http://lists.freedesktop.org/archives/poppler/2010-January/005446.html > http://lists.freedesktop.org/archives/poppler/2010-January/005453.html > > FcConfigReference() looks slightly better about its handling > of reference counter. Invoking FcConfigDestroy() for the > object obtained by FcConfigReference( NULL ) is safer than > the object obtained by FcConfigGetCurrent(). However, by P2, > the minimum reference counter of the object obtained by > FcConfigGetCurrent( NULL ) is 2, not 1. FcConfigGetCurrent() > sets the reference counter to 1, and FcConfigReference() > increments it. As a result, > - Invoke FcConfigReference( NULL ) once > - Invoke FcConfigDestroy( config ) twice > is required for real freeing of the FcConfig object. This is > not intuitive. > > In summary, I want to propose following modifications: > > M1) FcConfigGetCurrent() increments the reference counter > when it returns existing object. > > M2) FcConfigDestroy() does not increment the reference > counter when it is invoked with NULL pointer and > FcConfigGetCurrent() is invoked. > > Please give me comment. > > Regards, > mpsuzuki > _______________________________________________ > Fontconfig mailing list > Fontconfig at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/fontconfig >
mpsuzuki at hiroshima-u.ac.jp
2010-Jan-21 21:57 UTC
[Fontconfig] The reference counter handling in FcConfigGetCurrent() and FcConfigReference().
Hi, On Thu, 21 Jan 2010 15:32:55 -0500 Behdad Esfahbod <behdad at behdad.org> wrote:>What you are observing is simply that fontconfig is caching one instance of >FcConfig. That''s by design. If you want that freed, you can call FcFini().Hmm, if an application links multiple libraries that some of them call FcConfigGetCurrent() or FcInit() by themselves (so FcConfigGetCurrent() or FcInit() are called multiply), FcFini() should be called by the application to restrict only one freeing? Or, all libraries can call FcFini() by their own scope? As both of FcInit() and FcConfigCurrent() does not increment the reference counter, I''m afraid that multiple calls of FcFini() can cause freeing the object in use. Regards, mpsuzuki>That''s not a *leak*. A leak is memory lost. Forever. > >behdad > >On 01/21/2010 06:27 AM, mpsuzuki at hiroshima-u.ac.jp wrote: >> Dear fontconfig maintainers, >> >> FcConfig object includes its reference counter, it prevents >> that FcConfigDestroy() frees an object in use. I think it''s >> good design. >> >> In the current implementation, I''m questionable about 2 points: >> >> P1) FcConfigGetCurrent() does not increment the reference >> counter when it returns existing FcConfig object. >> >> P2) FcConfigReference() increments the reference counter >> even when it returns new object created by FcConfigGetCurrent(). >> >> By P1, some libraries linking other libraries which uses >> fontconfig too cannot free FcConfig object safely. >> >> For example, poppler links fontconfig by itself (to import >> font resources out of the document), and sometimes it links >> cairo (to render PDF to scalable graphics) which links >> fontconfig too. >> >> The poppler invokes FcConfigGetCurrent() when it reads >> given PDF document, and sometimes cairo invoked by poppler >> invokes FcConfigGetCurrent() again, to write an output file. >> Unfortunately, the dependency of poppler onto cairo is >> not essential, so, poppler does not pass FcConfig object >> to cairo. Also no cairo API takes FcConfig object from >> the caller. >> >> How we can free the object obtained by FcConfigGetCurrent()? >> In current implementation, we cannot know how many clients >> invoked FcConfigGetCurrent() from FcConfig->ref, so invoking >> FcConfigDestroy() is not safe. As a result, poppler does not >> invoke FcConfigDestroy() at all, although poppler frees an >> object including the reference to FcConfig obtained by >> FcConfigGetCurrent(). So, valgrind finds a memory leak in >> some programs. See recent discussion in poppler mail list: >> >> http://lists.freedesktop.org/archives/poppler/2010-January/005429.html >> http://lists.freedesktop.org/archives/poppler/2010-January/005446.html >> http://lists.freedesktop.org/archives/poppler/2010-January/005453.html >> >> FcConfigReference() looks slightly better about its handling >> of reference counter. Invoking FcConfigDestroy() for the >> object obtained by FcConfigReference( NULL ) is safer than >> the object obtained by FcConfigGetCurrent(). However, by P2, >> the minimum reference counter of the object obtained by >> FcConfigGetCurrent( NULL ) is 2, not 1. FcConfigGetCurrent() >> sets the reference counter to 1, and FcConfigReference() >> increments it. As a result, >> - Invoke FcConfigReference( NULL ) once >> - Invoke FcConfigDestroy( config ) twice >> is required for real freeing of the FcConfig object. This is >> not intuitive. >> >> In summary, I want to propose following modifications: >> >> M1) FcConfigGetCurrent() increments the reference counter >> when it returns existing object. >> >> M2) FcConfigDestroy() does not increment the reference >> counter when it is invoked with NULL pointer and >> FcConfigGetCurrent() is invoked. >> >> Please give me comment. >> >> Regards, >> mpsuzuki >> _______________________________________________ >> Fontconfig mailing list >> Fontconfig at lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/fontconfig >>
Chris Wilson
2010-Jan-22 10:51 UTC
[Fontconfig] The reference counter handling in FcConfigGetCurrent() and FcConfigReference().
On Fri, 22 Jan 2010 06:57:39 +0900, mpsuzuki at hiroshima-u.ac.jp wrote:> Hmm, if an application links multiple libraries that some > of them call FcConfigGetCurrent() or FcInit() by themselves > (so FcConfigGetCurrent() or FcInit() are called multiply), > FcFini() should be called by the application to restrict > only one freeing? Or, all libraries can call FcFini() by > their own scope?It would be a very bad design if any library attempted to finalize another shared resource at a random point in time, for precisely the reasons you have outlined. Cleaning up of global state can only be performed by the application once it has guaranteed that those resources are no longer in use - typically during the shutdown of the last thread, primarily for the purposes of leak checking. -ickle -- Chris Wilson, Intel Open Source Technology Centre
Behdad Esfahbod
2010-Jan-28 21:46 UTC
[Fontconfig] The reference counter handling in FcConfigGetCurrent() and FcConfigReference().
On 01/21/2010 04:57 PM, mpsuzuki at hiroshima-u.ac.jp wrote:> Hmm, if an application links multiple libraries that some > of them call FcConfigGetCurrent() or FcInit() by themselves > (so FcConfigGetCurrent() or FcInit() are called multiply), > FcFini() should be called by the application to restrict > only one freeing? Or, all libraries can call FcFini() by > their own scope?Yes, FcFini() may only be called by applications, not libraries. behdad