Hi Antony,
Could you open an issue and attach the full thread-dump (or at least the
'deadlocks' section that summarises the threads and locks involved in the
deadlock).
--
Cheers, Stuart
On 24 Sep 2012, at 04:55, Antony Stubbs wrote:
> Hi, we're experiencing a deadlock in our multi-threaded code, and I think
> I've tracked it down to our use of FactoryModuleBuilder to create one of our
> objects during an HTTP response. We use the pattern of:
> install(new FactoryModuleBuilder()
> .implement(User.class, User.class)
> .build(UserFactory.class));
>
> And our dead lock looks like (we have more than a dozen threads all blocked
> in the same way):
> "Thread-2616" prio=10 tid=0x00007f41647e1800 nid=0xea9 waiting for monitor
> entry [0x00007f417fefd000]
> java.lang.Thread.State: BLOCKED (on object monitor)
> at
> com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:102)
> - waiting to lock <0x0000000608d609a0> (a
> com.google.inject.internal.InheritingState)
> at
> com.google.inject.internal.InjectorImpl.createChildInjector(InjectorImpl.java:217)
> at
> com.google.inject.internal.InjectorImpl.createChildInjector(InjectorImpl.java:224)
> at
> com.google.inject.assistedinject.FactoryProvider2.getBindingFromNewInjector(FactoryProvider2.java:602)
> at
> com.google.inject.assistedinject.FactoryProvider2.invoke(FactoryProvider2.java:625)
> at $Proxy16.create(Unknown Source)
> at ourCode
>
> So I am concluding that the Factory Module Builder pattern isn't thread safe
> per-se, and will just go back to creating our object manually, then using
> injector#injectMembers() afterwards.
>
> Am I missing something or does this sound about right? Is this correct? Or am
> I missing something? If it is, it would be great to get a warning added
> somewhere..
>
> The relavent Guice code is FactoryProvider2:
> /**
> * When a factory method is invoked, we create a child injector that binds
> all parameters, then
> * use that to get an instance of the return type.
> */
> public Object invoke(Object proxy, final Method method, final Object[]
> args) throws Throwable {
>
> and then the synchro block in InternalInjectorCreator:
>
> public Injector build() {
> if (shellBuilder == null) {
> throw new AssertionError("Already built, builders are not reusable.");
> }
>
> // Synchronize while we're building up the bindings and other injector
> state. This ensures that
> // the JIT bindings in the parent injector don't change while we're being
> built
> synchronized (shellBuilder.lock()) {
> shells = shellBuilder.build(initializer, bindingData, stopwatch,
> errors);
> stopwatch.resetAndLog("Injector construction");
>
> initializeStatically();
> }
>
> injectDynamically();
>
> if (shellBuilder.getStage() == Stage.TOOL) {
> // wrap the primaryInjector in a ToolStageInjector
> // to prevent non-tool-friendy methods from being called.
> return new ToolStageInjector(primaryInjector());
> } else {
> return primaryInjector();
> }
> }
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-guice/-/BgAsyOu14cIJ.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.