Deadlock using FactoryModuleBuilder from different threads

71 views
Skip to first unread message

Antony Stubbs

unread,
Sep 23, 2012, 11:55:36 PM9/23/12
to google...@googlegroups.com
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();
    }
  }

Stuart McCulloch

unread,
Sep 24, 2012, 6:34:22 AM9/24/12
to google...@googlegroups.com
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

--
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 google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Antony Stubbs

unread,
Sep 24, 2012, 12:52:45 PM9/24/12
to google...@googlegroups.com, Chris Soyars
As requested:

Issue 729: Deadlock using FactoryModuleBuilder from different threads
Reply all
Reply to author
Forward
0 new messages