Home » Modeling » TMF (Xtext) » Deadlock during injector initialization
Deadlock during injector initialization [message #1679046] |
Mon, 16 March 2015 08:50  |
Eclipse User |
|
|
|
Hi,
I'm observing a deadlock during injector initialization, which seems to
be due to the synchronization in MyDslActivator.getInjector().
Here are the relevant parts of the two deadlocked threads:
Thread 1 triggered by the builder
Scopes$1$1.get() line: 64
InternalFactoryToProviderAdapter<T>.get(Errors, InternalContext, Dependency<?>, boolean) line: 40
InternalInjectorCreator$1.call(InternalContext) line: 204
InternalInjectorCreator$1.call(InternalContext) line: 198
InjectorImpl.callInContext(ContextualCallable<T>) line: 1024
InternalInjectorCreator.loadEagerSingletons(InjectorImpl, Stage, Errors) line: 198
InternalInjectorCreator.injectDynamically() line: 179
InternalInjectorCreator.build() line: 109
Guice.createInjector(Stage, Iterable<Module>) line: 95
Guice.createInjector(Iterable<Module>) line: 72
Guice.createInjector(Module...) line: 62
MyDslActivator(MyDslActivator).createInjector(String) line: 67
MyDslActivator.createInjector(String) line: 89
MyDslActivator.getInjector(String) line: 76
MyDslExecutableExtensionFactory.getInjector() line: 26
MyDslExecutableExtensionFactory(AbstractGuiceAwareExecutableExtensionFactory).create() line: 49
ConfigurationElement.createExecutableExtension(String) line: 262
ConfigurationElementHandle.createExecutableExtension(String) line: 55
ResourceServiceProviderDescriptor.get(URI, String) line: 39
ResourceServiceProviderRegistryImpl$InternalData.getServiceProvider(URI, String) line: 46
ResourceServiceProviderRegistryImpl.getResourceServiceProvider(URI, String) line: 108
ResourceServiceProviderRegistryImpl.getResourceServiceProvider(URI) line: 124
UriValidator.isValid(URI, IStorage) line: 27
Storage2UriMapperImpl.isValidUri(URI, IStorage) line: 233
Storage2UriMapperImpl.getUri(IStorage) line: 219
ToBeBuiltComputer.getUri(IStorage) line: 326
ToBeBuiltComputer.updateStorage(IProgressMonitor, ToBeBuilt, IStorage) line: 268
ToBeBuiltComputer$2.visit(IResource) line: 241
Resource$2.visit(IResourceProxy) line: 126
Resource$1.visitElement(ElementTree, IPathRequestor, Object) line: 85
ElementTreeIterator.doIteration(DataTreeNode, IElementContentVisitor) line: 82
ElementTreeIterator.doIteration(DataTreeNode, IElementContentVisitor) line: 86
ElementTreeIterator.doIteration(DataTreeNode, IElementContentVisitor) line: 86
ElementTreeIterator.doIteration(DataTreeNode, IElementContentVisitor) line: 86
ElementTreeIterator.iterate(IElementContentVisitor) line: 127
Project(Resource).accept(IResourceProxyVisitor, int, int) line: 95
Project(Resource).accept(IResourceProxyVisitor, int) line: 52
Project(Resource).accept(IResourceVisitor, int, int) line: 124
Project(Resource).accept(IResourceVisitor) line: 108
ToBeBuiltComputer.updateProject(IProject, IProgressMonitor) line: 236
ToBeBuiltComputer.updateProjectNewResourcesOnly(IProject, IProgressMonitor) line: 205
XtextBuilder.fullBuild(IProgressMonitor, boolean) line: 211
XtextBuilder.build(int, Map, IProgressMonitor) line: 89
Thread 2 triggered by initializing a view with injections
MyDslActivator.getInjector(String) line: 74
MyDslExecutableExtensionFactory.getInjector() line: 26
MyDslExecutableExtensionFactory(AbstractGuiceAwareExecutableExtensionFactory).create() line: 49
ConfigurationElement.createExecutableExtension(String) line: 262
ConfigurationElementHandle.createExecutableExtension(String) line: 55
ElementSelectionConverter.initialize(Injector) line: 52
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
SingleMethodInjector$1.invoke(Object, Object...) line: 71
SingleMethodInjector.inject(Errors, InternalContext, Object) line: 90
MembersInjectorImpl<T>.injectMembers(T, Errors, InternalContext, boolean) line: 110
ConstructorInjector<T>.construct(Errors, InternalContext, Class<?>, boolean) line: 94
ConstructorBindingImpl$Factory<T>.get(Errors, InternalContext, Dependency<?>, boolean) line: 254
ProviderToInternalFactoryAdapter$1.call(InternalContext) line: 46
InjectorImpl.callInContext(ContextualCallable<T>) line: 1031
ProviderToInternalFactoryAdapter<T>.get() line: 40
Scopes$1$1.get() line: 65
InternalFactoryToProviderAdapter<T>.get(Errors, InternalContext, Dependency<?>, boolean) line: 40
SingleFieldInjector.inject(Errors, InternalContext, Object) line: 53
MembersInjectorImpl<T>.injectMembers(T, Errors, InternalContext, boolean) line: 110
ConstructorInjector<T>.construct(Errors, InternalContext, Class<?>, boolean) line: 94
ConstructorBindingImpl$Factory<T>.get(Errors, InternalContext, Dependency<?>, boolean) line: 254
ProviderToInternalFactoryAdapter$1.call(InternalContext) line: 46
InjectorImpl.callInContext(ContextualCallable<T>) line: 1031
ProviderToInternalFactoryAdapter<T>.get() line: 40
Scopes$1$1.get() line: 65
InternalFactoryToProviderAdapter<T>.get(Errors, InternalContext, Dependency<?>, boolean) line: 40
InjectorImpl$4$1.call(InternalContext) line: 978
InjectorImpl.callInContext(ContextualCallable<T>) line: 1024
InjectorImpl$4.get() line: 974
InjectorImpl.getInstance(Class<T>) line: 1013
GraphViewExecutableExtensionFactory(AbstractGuiceAwareExecutableExtensionFactory).create() line: 50
ConfigurationElement.createExecutableExtension(String) line: 262
ConfigurationElementHandle.createExecutableExtension(String) line: 55
ViewDescriptor.createView() line: 63
Contention regards
- com.google.inject.internal.InternalInjectorCreator - owned by the view thread
- Collections$SynchronizedMap<K,V> - which is MyDslActivator.injectors - owned by the builder thread
Has anybody seen anything like this before?
The problem started to occur after adding just one more injected action to the view.
The action itself has the same set of injected fields as other actions do, none of which caused problems before. Perhaps the risk of deadlock has always been there?
Should the (generated) method getInjector() try to first acquire the lock on InternalInjectorCreator before taking its own lock?
Stephan
|
|
| | | | |
Re: Deadlock during injector initialization [message #1688485 is a reply to message #1679284] |
Fri, 20 March 2015 16:16  |
Eclipse User |
|
|
|
For posterity: I haven't observed this deadlock for some time now, which doesn't mean a whole lot, but I believe the below change in my activators did the trick:
@SuppressWarnings("restriction")
public Injector getInjector(String language) {
synchronized (com.google.inject.internal.InternalInjectorCreator.class) {
synchronized (injectors) {
Injector injector = injectors.get(language);
if (injector == null) {
injectors.put(language, injector = createInjector(language));
}
return injector;
}
}
}
I think one should never enter the inner synchronized block without owning the other lock that is necessary for successful completion of createInjector(..) -- in particular when several mechanisms for on-demand initialization are competing, like bundle activation, extension point evaluation and guice injection.
|
|
|
Goto Forum:
Current Time: Mon Jul 28 16:41:44 EDT 2025
Powered by FUDForum. Page generated in 0.03687 seconds
|