Closed eregon closed 1 year ago
What I need help with is whether this recursive call is intended and if we can avoid it.
For instance, does Sprockets::Bundle.call
needs to use the cached environment or could it call Sprockets::Loader#load
to avoid the recursion?
I've quickly tried to replace env.load
calls in Sprockets::Bundle.call
, but it also happens in SourceMapProcessor.call
.
Maybe we should detect the recursion in CachedEnvironment if Sprockets relies on these recursive calls causing cache miss to work fine?
@byroot Could you help me with this? Maybe we can have a call or something to discuss the solutions.
Note: we also need to care about the value being nil
possibly for those caches since https://github.com/rails/sprockets/pull/723.
Sprockets::Cache::MemoryStore (https://github.com/rails/sprockets/blob/main/lib/sprockets/cache/memory_store.rb) has similar thread safety problems, and that matches the other backtraces in the TruffleRuby issues linked in the description.
I have found a solution using Concurrent::Map#fetch_or_store
and updated https://github.com/rails/sprockets/pull/771.
And just a Mutex for Sprockets::Cache::MemoryStore
.
Sorry for all the messages/notifications here, I'm unfamiliar with Sprockets so wanted to make notes and talking points.
I'm still interested to understand a bit better about Sprockets and whether it's OK to cache miss 2+ times for the same key in CachedEnvironment (was already the case).
whether it's OK to cache miss 2+ times for the same key in CachedEnvironment (was already the case).
Yeah I think it's fine.
Sprockets::CachedEnvironment is not thread-safe: https://github.com/rails/sprockets/blob/1276b431e2e4c1099dae1b3ff76adc868c863ddd/lib/sprockets/cached_environment.rb#L34-L54 Specifically it mutates Hash instances concurrently.
Expected behavior
It should work.
Actual behavior
It crashes with various thread safety-related issues. For instance https://github.com/oracle/truffleruby/issues/2808 and https://github.com/oracle/truffleruby/issues/2804.
I tried the obvious approach of using
Concurrent::Map.new
+compute_if_absent
instead of a Hash in https://github.com/rails/sprockets/pull/771, but that doesn't work because Sprockets callsSprockets::CachedEnvironment#load
recursively (and on the same CachedEnvironment instance), e.g. (on CRuby):System configuration
Example App (Reproduction) - THIS IS IMPORTANT YOUR ISSUE LIKELY WILL NOT BE RESOLVED WITHOUT THIS
Running the tests on TruffleRuby (
bundle exec rake
) on TruffleRuby reproduce this issue. Also the command-line above is an easy way to reproduce it on branch https://github.com/rails/sprockets/pull/771.