google / google/guice

Deadlock in multi-threading enviroment (Guice 5.1)

Aperta
#1,663 2 commenti 1 reazione 0 assegnatari Vedi su GitHub
Lingua principale
Java
Stelle
12.7k
Fork
1.7k
Merge medio
11m
PR unite (30g)
2

Descrizione

It seems that there might be a deadlock in an environment when multiple binding types (JIT / Constructor / Member) are mixed We have found these thread dumps:
First:
```
qtp558569884-17964
at java.base@17.0.5/jdk.internal.misc.Unsafe.park(Native Method)
at java.base@17.0.5/java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:523)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:90)
at com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(Uninterruptibles.java:199)
at com.google.common.cache.LocalCache$LoadingValueReference.waitForValue(LocalCache.java:3581)
at com.google.common.cache.LocalCache$Segment.waitForLoadingValue(LocalCache.java:2174)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2038)
at com.google.common.cache.LocalCache.get(LocalCache.java:3952)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)
at com.google.inject.internal.FailableCache.get(FailableCache.java:54)
at com.google.inject.internal.MembersInjectorStore.get(MembersInjectorStore.java:69)
at com.google.inject.internal.ConstructorInjectorStore.createConstructor(ConstructorInjectorStore.java:75)
at com.google.inject.internal.ConstructorInjectorStore.access$000(ConstructorInjectorStore.java:30)
at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:38)
at com.google.inject.internal.ConstructorInjectorStore$1.create(ConstructorInjectorStore.java:34)
at com.google.inject.internal.FailableCache$1.load(FailableCache.java:43)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3528)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2277)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2154)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2044)
at com.google.common.cache.LocalCache.get(LocalCache.java:3952)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)
at com.google.inject.internal.FailableCache.get(FailableCache.java:54)
at com.google.inject.internal.ConstructorInjectorStore.get(ConstructorInjectorStore.java:49)
at com.google.inject.internal.ConstructorBindingImpl.initialize(ConstructorBindingImpl.java:152)
at com.google.inject.internal.InjectorImpl.initializeJitBinding(InjectorImpl.java:605)
at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:943)
at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:863)
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:300)
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:223)
at com.google.inject.internal.InjectorImpl.getProviderOrThrow(InjectorImpl.java:1093)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1122)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1087)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1139)
.....
```

and second:
```
at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:265)
at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:223)
at com.google.inject.internal.SingleFieldInjector.(SingleFieldInjector.java:39)
at com.google.inject.internal.MembersInjectorStore.getInjectors(MembersInjectorStore.java:131)
at com.google.inject.internal.MembersInjectorStore.createWithListeners(MembersInjectorStore.java:97)
at com.google.inject.internal.MembersInjectorStore.access$000(MembersInjectorStore.java:40)
at com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:49)
at com.google.inject.internal.MembersInjectorStore$1.create(MembersInjectorStore.java:45)
at com.google.inject.internal.FailableCache$1.load(FailableCache.java:43)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3528)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2277)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2154)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2044)
at com.google.common.cache.LocalCache.get(LocalCache.java:3952)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)
at com.google.inject.internal.FailableCache.get(FailableCache.java:54)
at com.google.inject.internal.MembersInjectorStore.get(MembersInjectorStore.java:69)
at com.google.inject.internal.InjectorImpl.getMembersInjector(InjectorImpl.java:1072)
at com.google.inject.internal.InjectorImpl.getMembersInjector(InjectorImpl.java:1082)
at com.google.inject.internal.InjectorImpl.injectMembers(InjectorImpl.java:1061)
```

Unfortunately, our setup is quite huge.. thousands of bindings and quite often we are obtaining instances directly from injector. (we are in a process of transformation to proper DI). So I can't provide you with more details now. I'm trying to create minimal test case for now without luck

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia tracciando i percorsi di InjectorImpl, ConstructorInjectorStore e MembersInjectorStore mostrati nel thread, insieme all’uso di FailableCache da parte di Guice. Crea un caso di test concorrente minimo che combini binding JIT, di costruttore e dei membri. Il lavoro è completo quando il deadlock viene riprodotto in modo affidabile e il comportamento rilevante è coperto da un test di regressione.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
java
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Tranquilla
Chiarezza
Da chiarire
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.