-
-
Notifications
You must be signed in to change notification settings - Fork 915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multithreaded code with function calls fail in precompiled JRuby classes #6210
Comments
At first it looked like the issue was with function calls with symbol procs, for examples:
But then, I could get it to fail with this version as well:
Hence, I updated the issue. |
Here's something interesting / disturbing about this issue: The first version of Even if I replace the
If I run |
Bleh...This one is aggravating but fairly mundane as to cause. We lazily decode scopes with this line: scope.allocateInterpreterContext(() -> file.decodeInstructionsAt(scope, poolOffset, instructionsOffset)); This java closure captures the IRReader instance it is in which has a field 'buf' which decodeEncoding() uses. Two or more threads using the same field at the same time without locks == boom. Until we release (and apply a fix for this) the only work around would be to load this code once in a single thread. After that point it sould be good for multi-threaded use. It is interesting that one example happens to hit it less than the other but I am guessing you are just getting lucky that two versions deserializing at the same time is out of sync enough to how happen to be doing encoding decoding at the same time. |
Ah -- that totally makes sense! Thank you Thomas! I would guess that what is happening with the differential impact is the speed at which the deserialization happens: the faster something deserializes (e.g., with just a constant in the function body) the less likely it is we'll have more than one thread attempting deserialization. |
We've also hit this issue, it's a blocker for us moving from JRuby 9.2.9.0 and thus a blocker for us to get to JDK11. Would really help us out if this bug could get fixed on the 9.2.11.x line. |
Instruction reading is done lazily to avoid the cost of deserializing method bodies that will never be called. However the buffer associated with the original file was being shared across all of these lazy deserializations, causing concurrency issues. This patch modifies the lazy deserialization lambda to operate against a duplicate of the original reader, isolating its changes in a separate buffer and avoiding the concurrency issues. Fixes jruby#6210
I've pushed a fix for this in #6275 that duplicates the IRReaderStream before doing any lazy instruction deserialization. This avoids two threads sharing a buffer and stepping on each other. We've also had a request for a shorter-term release with this fix, like a 9.2.11.2. We have no plans to do that right now, but with 9.3 growing into a "fix everything" release there may be justification for a 9.2.12. |
@enebo We need to talk about getting this fix and a few others into a 9.2.12, since I think we have at least another month of work to get 9.3 out the door. |
Awesome, thank you! |
@headius agreed this should be in 9.2.12. Added the milestone since we have already decided it to be a good idea and targetted this. We need to still cp this over to jruby-9.2 branch. |
Instruction reading is done lazily to avoid the cost of deserializing method bodies that will never be called. However the buffer associated with the original file was being shared across all of these lazy deserializations, causing concurrency issues. This patch modifies the lazy deserialization lambda to operate against a duplicate of the original reader, isolating its changes in a separate buffer and avoiding the concurrency issues. Fixes #6210
Done. |
On JRuby 9.2.9.0, we can successfully run code that calls functions within a
Thread
from pre-compiled JRuby classes.The exact same situation (pre-compiled JRuby classes, multi-threaded code that calls a function) crashes on JRuby 9.2.10.0 and JRuby 9.2.11.0 (haven't tested 9.2.11.1 or 9.3).
We are running JDK1.8, and have been able to reproduce this on MacOS, Ubuntu, and Alpine. We have also been able to reproduce with both the default
JRUBY_OPTS
, and also withcompile.invokedynamic=true
.FWIW, the same code with
NUM_THREADS = 1
succeeds when run from a pre-compiled JRuby class (fails forNUM_THREADS
> 1)Here are the steps to reproduce the bug:
jrubyc
jruby test.class
Expected Behavior
When compiled and run using JRuby 9.2.9.0, this test should return a number near
0.5
.Actual Behavior
When compiled and run using JRuby 9.2.10.0 and JRuby 9.2.11.0 (again, haven't tested beyond those), this same test crashes with the following stack trace:
The text was updated successfully, but these errors were encountered: