spring-cloud / spring-cloud/spring-cloud-commons

DeadLock on simultanously accessing uninitialized RefreshScope-Bean

Open
#383 11 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
751
Forks
744
Avg merge
1d 14h
Merged PRs (30d)
9

Description

Hi!

I'm using version 2.0.0.M9. Sometimes my application runs into a deadlock. This happens when two threads are simultanously accessing an uninitialized RefreshScope Bean.

My application uses the annotations NewSpan and Async . Both annotations cause access to a ProbabilityBasedSampler, that's provided as RefreshScope-Bean by ZipkinAutoConfiguration.RefreshScopedProbabilityBasedSamplerConfiguration.defaultTraceSampler(SamplerProperties).

Thread 1 creates a Singleton-Bean, with a @PostConstruct calling a sampled method (@Async-annotation). Thread 2 calls a sampled method (@NewSpan-annotation). ProbabilityBasedSampler and SamplerProperties are not yet initialized.

This is what happens:

  1. Thread 1: tries to create the Singleton, accesses DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>) and locks DefaultSingletonBeanRegistry.singletonObjects

  2. Thread 2: calls a @NewSpan-annotated method. This requires the ProbabilityBasedSampler and triggers GenericScope.BeanLifecycleWrapper.getBean() and locks GenericScope.BeanLifecycleWrapper.name

  3. Thread 2: to create ProbabilityBasedSampler the SamplerProperties are required. The bean factory tries to get the SamplerProperties-Singleton, but has to wait for the lock on DefaultSingletonBeanRegistry.singletonObjects that is held by Thread 1

  4. Thread 1: the @PostConstruct calls a @Async-annotated method, that requires ProbabilityBasedSampler. that triggers GenericScope.BeanLifecycleWrapper.getBean(), but has to wait for the lock GenericScope.BeanLifecycleWrapper.name held by Thread 2

I attach a class that simulates the behaviour of my application setup and the stack trace when this class runs into the deadlock: RefreshScopeDeadLock.zip

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Unpack RefreshScopeDeadLock.zip and start with the included reproducer and stack trace. Trace the two-thread interaction through DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>) and GenericScope.BeanLifecycleWrapper.getBean(), focusing on ProbabilityBasedSampler and SamplerProperties initialization. Done means the reported simultaneous access no longer deadlocks.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.