[ART-380] Fix ArgumentError due to concurrent require and class use #1354
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
If for some reason multiple tracers are initializing concurrently (see customer issue in #1306 or the flaky test in
tracer_integration_spec.rb
also fixed by this PR), multiple threads can try to rundefault_statsd_client
concurrently.Because Ruby
require
s are not atomic (e.g. you can observe classes that are half-loaded), our conditionalcould try to create a
Statsd
instance BEFORE the class was fully defined, leading toArgumentError: wrong number of arguments (given 2, expected 0)
when callinginitialize
. This error stems from the custom#initialize
method not being available yet, so Ruby falls back toObject#initialize
, which does not take any argument.See also:
The fix in this case is to always call
require
. Callingrequire
repeatedly has little impact -- a given file is only loaded byrequire
the first time AND concurrentrequire
s are protected -- only one thread will get to execute the require, will all others wait until it finishes.The follow example demonstrates this:
lazy-require.rb
:lazy-require-sleep-1.rb
:Notice how two threads tried to require, but only one actually ran the code on the other file, while the other was blocked and only woke up after the
require
finished.Fixes #1306