[OpenJDK 2D-Dev] Deadlock in SunGraphicsEnvironment / FontManager?

Jeremy Manson jeremymanson at google.com
Fri Oct 2 16:16:07 UTC 2009


Phil,

Thanks for responding.  I'm sorry about the lack of detail in the
stack traces: I wanted to take out the bits that were specific to our
application.  Given the line numbers, I thought it would be relatively
easy to determine what the locks were.

The reason I didn't want to fix it is because I would need to take a
detailed look at the code before I really understood what a fix should
look like.  As you pointed out, my first instinct about a fix was
wrong.  Any chance that this is now on someone else's radar?  For
example, the code's author?

Are the locks grabbed just to check to see if initialization was done?
That would imply that even if I did load the fonts at a safe point, I
could still potentially run into this problem later when the code
checks to see if the fonts are initialized.

Avoiding it is, unfortunately, not really an option.  We need fonts.  :)

Jeremy

On Thu, Oct 1, 2009 at 3:18 PM, Phil Race <Phil.Race at sun.com> wrote:
>
>
> Jeremy Manson wrote:
>>
>> Does anyone have any thoughts about this?  If we were to make up a
>> patch, would you take it?
>
> In summary the situation looks like this, (although your dumps
> aren't showing the locks, which I'd expected to see) :
>
> Thread 1 -> SunGraphicsEnvironment.loadFonts()
>              [locked on SunGraphicsEnvironment.lucidaFontName]
> Thread 2 -> FontManager.initialiseDeferredFonts()
>              [ locked on FontManager.class]
> Thread 1 -> FontManager.initialiseDeferredFonts()
>              [ .. waiting for lock on FontManager.class]
> Thread 1 -> SunGraphicsEnvironment.loadFonts()
>              [ .. waiting for lock on SunGraphicsEnvironment.lucidaFontName
> ]
>
>
> I'm not sure that the fix you suggest of moving the lock acquistion after
>      467             FontManager.initialiseDeferredFonts();
> is guaranteed to be sufficient. This next line (and perhaps others) :
>      473                         fontPath =
> getPlatformFontPath(noType1Font);
>
> will also also acquire the lock. Another option is to simplify this down
> to one lock : the FontManager.class one, using it instead of the
> SunGraphicsEnvironment.lucidaFontName lock which I think was used
> in preference to the normal FontManager lock to make sure that
> this lengthy loadfonts operation didn't freeze the rest of the font system
> until it completed.
> That should still be a concern, albeit less of a one than a deadlock.
> Another approach might be to eliminate the lock here and rely on
> checks in the registration methods by font file name to skip
> over much of the duplicate work that might ensue from letting
> two threads have at this at the same time. But that would need
> even more careful testing than the other approach. I think either
> approach should to be tested on Windows as well.
>
>>
>> I did get an email about how this should all be single threaded on an
>> event dispatcher thread, to which I would reply:
>>
>> 1) If it is all supposed to be single threaded, then there shouldn't
>> be any locks in it to cause a deadlock, and
>>
>> 2) This is in the font code, and you can use fonts for things other
>> than drawing to the screen (in this case, they are trying to render a
>> PDF).
>
> You are correct on this.
> Its interesting that its taken this long to show up. I suspect that
> you are running on a Linux system with a lot of fonts and its the
> amount of time you end spending in loadFonts() that contributes
> to another thread showing up in the middle of it.
>
> You could
> (a) trigger a load fonts (GraphicsEnvironment.getAllFonts()) at some
> known safe point in your app, or
> (b) try to avoid it. This might be tricky as if your app needs to
> go hunt down fonts at some point you'll hit loadfonts().
>
>
>
> -phil.
>
>>
>> Jeremy
>>
>> On Wed, Sep 23, 2009 at 5:16 PM, Jeremy Manson <jeremymanson at google.com>
>> wrote:
>>>
>>> Hi 2d folks,
>>>
>>> We have an application running on OpenJDK6 that seems to be
>>> deadlocking in SunGraphicsEnvironment.  I found it rather difficult to
>>> write a cut-down reproduction, but the errant lock acquisition is on
>>> line 482 of SunGraphicsEnvironment.java.:
>>>
>>>
>>> http://hg.openjdk.java.net/jdk6/jdk6-gate/jdk/file/f9fa5c538031/src/share/classes/sun/java2d/SunGraphicsEnvironment.java
>>>
>>> After the lock is acquired, it goes on to call
>>> FontManager.initialiseDeferredFonts() on line 467, which acquires the
>>> other lock.  It looks as if you might be able to move the lock
>>> acquisition from line 462 to 468, which would eliminate the deadlock.
>>> The code looks pretty similar in recent OpenJDK7 builds (although the
>>> line numbers are changed).
>>>
>>> The relevant stacks follow.  It seems like a pretty easy fix for a
>>> pretty nasty problem.  Any chance someone could take a look?  Thanks!
>>>
>>> Thread 1:
>>>  sun.font.FontManager.initialiseDeferredFonts(FontManager.java:791)
>>>
>>>  sun.java2d.SunGraphicsEnvironment.loadFonts(SunGraphicsEnvironment.java:467)
>>>
>>>  sun.awt.X11GraphicsEnvironment.loadFonts(X11GraphicsEnvironment.java:885)
>>>  sun.font.FontManager.findFont2D(FontManager.java:1995)
>>>  java.awt.Font.getFont2D(Font.java:473)
>>>  java.awt.Font.getFontName(Font.java:1221)
>>>  java.awt.Font.getFontName(Font.java:1203)
>>>
>>> Thread 2:
>>>
>>>  sun.java2d.SunGraphicsEnvironment.loadFonts(SunGraphicsEnvironment.java:463)
>>>
>>>  sun.awt.X11GraphicsEnvironment.loadFonts(X11GraphicsEnvironment.java:885)
>>>  sun.font.FontManager.findFont2D(FontManager.java:1995)
>>>  sun.font.FontManager.getDefaultPhysicalFont(FontManager.java:1071)
>>>  sun.font.FontManager.initialiseDeferredFont(FontManager.java:960)
>>>  sun.font.FontManager.findJREDeferredFont(FontManager.java:875)
>>>  sun.font.FontManager.findDeferredFont(FontManager.java:912)
>>>  <snip lots of recursion>
>>>  sun.font.FontManager.findFont2D(FontManager.java:1904)
>>>  sun.font.FontManager.findFont2D(FontManager.java:1865)
>>>  java.awt.Font.getFont2D(Font.java:473)
>>>  java.awt.Font.getFontName(Font.java:1221)
>>>  java.awt.Font.getFontName(Font.java:1203)
>>>
>



More information about the 2d-dev mailing list