Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Deadlock during EPackage initialization for cyclic package interdependencies
Deadlock during EPackage initialization for cyclic package interdependencies [message #1695038] Mon, 11 May 2015 14:17 Go to next message
Idrissa Dieng is currently offline Idrissa DiengFriend
Messages: 11
Registered: April 2013
Location: Paris, France
Junior Member
Hi all,
We encountered a deadlock problem during EMF packages initialization when using at least 2 threads. Indeed, there are cyclic package interdependencies between the various packages of our metamodel and we observed the issue when thread-1 triggers a package initialization and the thread-2 tries getting the eINSTANCE field via Java reflexivity (EPackage.Descriptor#getEPackage()).

The following describes the stack trace:
• Worker-1 starts at first & Worker-2 stats after Worker-1
• Worker-2 tries initiating EcucparameterdefPackageImpl.init() (that tries acceding to EcuresourcePackageImpl (see line in stack trace))
• Worked-1 tries acceding to EcucdescriptionPackageImpl.init() (after Worker-2 has started and that tries acceding EcucparameterdefPackageImpl)

==== Worker-1 (starts at first)
sun.misc.Unsafe.ensureClassInitialized(Class)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
java.lang.reflect.Field.acquireFieldAccessor(boolean)
java.lang.reflect.Field.getFieldAccessor(Object)
java.lang.reflect.Field.get(Object)
org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
RegistryReader.java:273
org.eclipse.emf.ecore.impl.EPackageImpl$1.getEPackage()
EPackageImpl.java:163
org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
EPackageRegistryImpl.java:127
autosar40.ecucdescription.impl.EcucdescriptionPackageImpl.init()
EcucdescriptionPackageImpl.java:1202
autosar40.ecucdescription.EcucdescriptionPackage.<clinit>()
...
autosar40.ecuresource.impl.EcuresourcePackageImpl.init()
EcuresourcePackageImpl.java:1051
autosar40.ecuresource.EcuresourcePackage.<clinit>()
EcuresourcePackage.java:78
sun.misc.Unsafe.ensureClassInitialized(Class)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
java.lang.reflect.Field.acquireFieldAccessor(boolean)
java.lang.reflect.Field.getFieldAccessor(Object)
java.lang.reflect.Field.get(Object)
org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
RegistryReader.java:273
org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
EPackageRegistryImpl.java:127
autosar40.commonstructure.internalbehavior.impl.InternalbehaviorPackageImpl.init()
InternalbehaviorPackageImpl.java:1036
autosar40.commonstructure.internalbehavior.InternalbehaviorPackage.<clinit>()
InternalbehaviorPackage.java:79
xyz.sym10.impl.Sym10PackageImpl.init()
Sym10PackageImpl.java:2810
xyz.Sym10Package.<clinit>() Sym10Package.java:71
sun.misc.Unsafe.ensureClassInitialized(Class)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
java.lang.reflect.Field.acquireFieldAccessor(boolean)
java.lang.reflect.Field.getFieldAccessor(Object)
java.lang.reflect.Field.get(Object)
org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
RegistryReader.java:273
org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
...

==== Worker-2 (starts after Worker-1)
sun.misc.Unsafe.ensureClassInitialized(Class)
sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
java.lang.reflect.Field.acquireFieldAccessor(boolean)
java.lang.reflect.Field.getFieldAccessor(Object)
java.lang.reflect.Field.get(Object)
org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
RegistryReader.java:273
org.eclipse.emf.ecore.impl.EPackageImpl$1.getEPackage()
EPackageImpl.java:163
org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
autosar40.ecucparameterdef.impl.EcucparameterdefPackageImpl.init()
autosar40.ecucparameterdef.EcucparameterdefPackage.<clinit>()
org.artop.ecuc.autosar4x.dsl.values.ecucValuesDsl.impl.EcucValuesDslPackageImpl.init()
org.artop.ecuc.autosar4x.dsl.values.ecucValuesDsl.EcucValuesDslPackage.<clinit>()
xyz.ecuc.values.validation.internal.EcucValuesDslExternalValidatorDelegate.getEPackages()
...

Changed the EPackageImpl implementation as described below fixed the deadlock issue in our side. We know that the original EMF code is there for some reasons. Therefore, why not returning the same EPackage instances also when the threads are different?
Can you please tell us if using the same EPackage instances will have side effects? Or do you have any suggestion(s) for resolving this deadlock issue?


Original EMF Code

protected EPackageImpl(String packageURI, final EFactory factory)
{
super();

Object registration = Registry.INSTANCE.get(packageURI);
if (registration instanceof Descriptor)
{
final Descriptor descriptor = (Descriptor)registration;
final long threadId = Thread.currentThread().getId();
Registry.INSTANCE.put
(packageURI,
new Descriptor()
{
public EPackage getEPackage()
{
return Thread.currentThread().getId() == threadId ? EPackageImpl.this : descriptor.getEPackage();
}

public EFactory getEFactory()
{
return Thread.currentThread().getId() == threadId ? factory : descriptor.getEFactory();
}
});
}
...
}

Our solution to fix the deadlock issue is returning always EPackageImpl.this & factory to use same instances.

Thanks in advance
Re: Deadlock during EPackage initialization for cyclic package interdependencies [message #1695051 is a reply to message #1695038] Mon, 11 May 2015 15:35 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
Idrissa,

Comments below.


On 11/05/2015 4:17 PM, Idrissa Dieng wrote:
> Hi all,
> We encountered a deadlock problem during EMF packages initialization
> when using at least 2 threads.
Which version of EMF?

> Indeed, there are cyclic package interdependencies between the various
> packages of our metamodel and we observed the issue when thread-1
> triggers a package initialization and the thread-2 tries getting the
> eINSTANCE field via Java reflexivity (EPackage.Descriptor#getEPackage()).
> The following describes the stack trace:
> • Worker-1 starts at first & Worker-2 stats after Worker-1
> • Worker-2 tries initiating EcucparameterdefPackageImpl.init()
> (that tries acceding to EcuresourcePackageImpl (see line in stack trace))
> • Worked-1 tries acceding to EcucdescriptionPackageImpl.init()
> (after Worker-2 has started and that tries acceding
> EcucparameterdefPackageImpl)
>
> ==== Worker-1 (starts at first)
> sun.misc.Unsafe.ensureClassInitialized(Class)
> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
> sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
> java.lang.reflect.Field.acquireFieldAccessor(boolean)
> java.lang.reflect.Field.getFieldAccessor(Object)
> java.lang.reflect.Field.get(Object)
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
>
> RegistryReader.java:273
> org.eclipse.emf.ecore.impl.EPackageImpl$1.getEPackage()
> EPackageImpl.java:163
> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
> EPackageRegistryImpl.java:127
> autosar40.ecucdescription.impl.EcucdescriptionPackageImpl.init()
> EcucdescriptionPackageImpl.java:1202
> autosar40.ecucdescription.EcucdescriptionPackage.<clinit>()
> ..
> autosar40.ecuresource.impl.EcuresourcePackageImpl.init()
> EcuresourcePackageImpl.java:1051
> autosar40.ecuresource.EcuresourcePackage.<clinit>()
> EcuresourcePackage.java:78
> sun.misc.Unsafe.ensureClassInitialized(Class)
> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
> sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
> java.lang.reflect.Field.acquireFieldAccessor(boolean)
> java.lang.reflect.Field.getFieldAccessor(Object)
> java.lang.reflect.Field.get(Object)
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
>
> RegistryReader.java:273
> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
> EPackageRegistryImpl.java:127
> autosar40.commonstructure.internalbehavior.impl.InternalbehaviorPackageImpl.init()
>
> InternalbehaviorPackageImpl.java:1036
> autosar40.commonstructure.internalbehavior.InternalbehaviorPackage.<clinit>()
>
> InternalbehaviorPackage.java:79
> xyz.sym10.impl.Sym10PackageImpl.init()
> Sym10PackageImpl.java:2810
> xyz.Sym10Package.<clinit>() Sym10Package.java:71
> sun.misc.Unsafe.ensureClassInitialized(Class)
> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
> sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
> java.lang.reflect.Field.acquireFieldAccessor(boolean)
> java.lang.reflect.Field.getFieldAccessor(Object)
> java.lang.reflect.Field.get(Object)
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
>
> RegistryReader.java:273
> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
> ..
>
> ==== Worker-2 (starts after Worker-1)
> sun.misc.Unsafe.ensureClassInitialized(Class)
> sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Field, boolean)
> sun.reflect.ReflectionFactory.newFieldAccessor(Field, boolean)
> java.lang.reflect.Field.acquireFieldAccessor(boolean)
> java.lang.reflect.Field.getFieldAccessor(Object)
> java.lang.reflect.Field.get(Object)
> org.eclipse.emf.ecore.plugin.RegistryReader$EPackageDescriptor.getEPackage()
>
> RegistryReader.java:273
> org.eclipse.emf.ecore.impl.EPackageImpl$1.getEPackage()
> EPackageImpl.java:163
> org.eclipse.emf.ecore.impl.EPackageRegistryImpl.getEPackage(String)
> autosar40.ecucparameterdef.impl.EcucparameterdefPackageImpl.init()
> autosar40.ecucparameterdef.EcucparameterdefPackage.<clinit>()
> org.artop.ecuc.autosar4x.dsl.values.ecucValuesDsl.impl.EcucValuesDslPackageImpl.init()
> org.artop.ecuc.autosar4x.dsl.values.ecucValuesDsl.EcucValuesDslPackage.<clinit>()
>
> xyz.ecuc.values.validation.internal.EcucValuesDslExternalValidatorDelegate.getEPackages()
>
> ..
>
> Changed the EPackageImpl implementation as described below fixed the
> deadlock issue in our side. We know that the original EMF code is
> there for some reasons.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=270865
> Therefore, why not returning the same EPackage instances also when the
> threads are different?
I'm not sure I understand the question...
> Can you please tell us if using the same EPackage instances will have
> side effects?
Given I don't understand the question, it's hard to comment.
> Or do you have any suggestion(s) for resolving this deadlock issue?
In the worst case, make sure you initialize the packages on a single
thread earlier during initialization.
>
> Original EMF Code
>
> protected EPackageImpl(String packageURI, final EFactory factory)
> {
> super();
>
> Object registration = Registry.INSTANCE.get(packageURI);
> if (registration instanceof Descriptor)
> {
> final Descriptor descriptor = (Descriptor)registration;
> final long threadId = Thread.currentThread().getId();
> Registry.INSTANCE.put
> (packageURI, new Descriptor()
> {
> public EPackage getEPackage()
> {
> return Thread.currentThread().getId() == threadId ?
> EPackageImpl.this : descriptor.getEPackage();
> }
>
> public EFactory getEFactory()
> {
> return Thread.currentThread().getId() == threadId ?
> factory : descriptor.getEFactory();
> }
> });
> }
> ...
> }
>
> Our solution to fix the deadlock issue is returning always
> EPackageImpl.this & factory to use same instances.
Another approach might be to access the XyzPackage.eINSTANCE values
earlier in the application.

In the end this problem is nasty and even Java is designed so that it's
possible that XyzPackage.eINSTANCE return null in a multi-thread
scenario because it ensures that class loading never deadlocks, at the
cost of constants that in theory can't possibly be null, in theory,
being null nevertheless.
>
> Thanks in advance
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Deadlock during EPackage initialization for cyclic package interdependencies [message #1695113 is a reply to message #1695051] Tue, 12 May 2015 07:04 Go to previous messageGo to next message
Andreas Graf is currently offline Andreas GrafFriend
Messages: 211
Registered: July 2009
Senior Member
Hi Ed,
the application in question is a RCP, so the initialization is done through the normal bundle startup.
If you are suggesting that the package should be initialized earlier, would that mean in a bundle with a lower start-level?
Re: Deadlock during EPackage initialization for cyclic package interdependencies [message #1695117 is a reply to message #1695051] Tue, 12 May 2015 07:26 Go to previous message
Idrissa Dieng is currently offline Idrissa DiengFriend
Messages: 11
Registered: April 2013
Location: Paris, France
Junior Member
Hi Ed,
Thanks for your quite reply we are using EMF 2.10 from Luna
I will have a Look on the pointed bug

[Updated on: Tue, 12 May 2015 07:27]

Report message to a moderator

Previous Topic:Missing "new child" menu entry
Next Topic:[Xcore] Adding new super class to all classes in an EMF model
Goto Forum:
  


Current Time: Fri Apr 26 01:31:06 GMT 2024

Powered by FUDForum. Page generated in 0.03783 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top