Skip to main content



      Home
Home » Modeling » TMF (Xtext) » Deadlock during injector initialization
Deadlock during injector initialization [message #1679046] Mon, 16 March 2015 08:50 Go to next message
Eclipse UserFriend
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 #1679085 is a reply to message #1679046] Mon, 16 March 2015 09:11 Go to previous messageGo to next message
Eclipse UserFriend
Hi,

can you tell why GraphViewExecutableExtensionFactory triggers MyDslExecutableExtensionFactory?
Re: Deadlock during injector initialization [message #1679204 is a reply to message #1679085] Mon, 16 March 2015 10:11 Go to previous messageGo to next message
Eclipse UserFriend
MyDsl provides an extension to an extension point in GraphView, or more correctly: I have a fragment to GraphView, which provides these extensions using MyDslExecutableExtensionFactory.

Looking at this more closely I can see that the above creates an implicit dependency cycle. I did this in an attempt to follow Jan's advice in the GraphView README. So maybe either that advice was bad or I misunderstood it in some way.

Stephan
Re: Deadlock during injector initialization [message #1679253 is a reply to message #1679204] Mon, 16 March 2015 10:37 Go to previous messageGo to next message
Eclipse UserFriend
hi,

shouldnt each plugin have its own ExecutableExtensionFactory + injector?
Re: Deadlock during injector initialization [message #1679284 is a reply to message #1679253] Mon, 16 March 2015 10:50 Go to previous messageGo to next message
Eclipse UserFriend
as per Jan's hint, the fragment is only glue: it plugs the DSL into GraphView. For that reason it doesn't have it's own ExecutableExtensionFactory + injector but refers to those of the DSL.
Re: Deadlock during injector initialization [message #1688485 is a reply to message #1679284] Fri, 20 March 2015 16:16 Go to previous message
Eclipse UserFriend
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.
Previous Topic:Serialization issues
Next Topic:Generating Xtend code
Goto Forum:
  


Current Time: Mon Jul 28 16:41:44 EDT 2025

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

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

Back to the top