Hi Chris,

Thanks. Here's the bug:

   private List<Locale> getJRELocales() {
        if (availableJRELocales == null) {
            synchronized (LocaleServiceProviderPool.class) {
                if (availableJRELocales == null) {
                    Locale[] allLocales = LocaleData.getAvailableLocales();
availableJRELocales = new ArrayList<Locale>(allLocales.length); <<==== YIKES we just published an empty ArrayList
                    for (Locale locale : allLocales) {
                        availableJRELocales.add(getLookupLocale(locale));
                    }
                }
            }
        }
        return availableJRELocales;
    }


availableJRELocales is a static variable shared across all pools. But it is being published before it gets populated. We need to use a temporary for the new ArrayList and only assign to availableJRELocales after it is populated.

In addition, as you mentioned, availableJRELocales needs to be volatile for this DCL pattern to be correct.

Thanks,
David

On 6/10/2011 9:02 PM, Chris Hegarty wrote:
I see several exceptions, similar to the following (numbers vary):

Exception in thread "Thread-23"
java.util.ConcurrentModificationException: Expected: 96, got: 156
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at java.util.AbstractCollection.addAll(AbstractCollection.java:333)
at java.util.HashSet.<init>(HashSet.java:117)
at
sun.util.LocaleServiceProviderPool.getAvailableLocales(LocaleServiceProviderPool.java:206)

at Interrupter$TestThread.run(Interrupter.java:49)



There would appear to be 156 JRE Locales ( at least on this system ),
modCount is incremented for each add(), but when the iterator is created
( implicitly during the HastSet.addAll ) it sees a different value for
modCount.

I think there is a visibility issue here. availableJRELocales is
volatile, but the List reference returned from getJRELocales is not. In
the case where availableJRELocales is not null there will be no memory
barrier to force a HB relationship. Or maybe I've gotten this wrong? His
is quite bizarre, or maybe it is just the overly complicated use of
locking/DCL in this class.

-Chris.

On 10/ 5/11 07:01 PM, David Holmes wrote:
This might not be related to the CME problem, but here:

public static LocaleServiceProviderPool getPool(Class<? extends
LocaleServiceProvider> providerClass) {
LocaleServiceProviderPool pool = poolOfPools.get(providerClass);
if (pool == null) {
LocaleServiceProviderPool newPool =
new LocaleServiceProviderPool(providerClass);
pool = poolOfPools.put(providerClass, newPool);
if (pool == null) {
pool = newPool;
}
}

return pool;
}

we should probably be using poolOfPools.putIfAbsent(providerClass,
newPool)

David

On 6/10/2011 3:35 AM, Naoto Sato wrote:
I will look into this. Reopened the original CR.

Naoto

On 10/5/11 9:58 AM, Alan Bateman wrote:
Chris Hegarty wrote:
Alan, Naoto, David

I filed CR 7098100: java/util/Locale/Bug6989440.java fails
intermittently.

If you're ok with it please review the patch (below) and I can push it
to the tl repo. Job done!
I assume there is also some underlying issue in the Locale code and
this
might get hidden if we fix the test (I"ve no objection to fixing the
test of course, just thinking that we should study the Locale code to
try to identify the deadlock or hang or whatever it is that is causing
the threads in this test not to terminate).

-Alan

Reply via email to