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

Phil Race Phil.Race at Sun.COM
Thu Oct 1 22:18:24 UTC 2009

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().


> 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