ScriptingContainer.put() does not always work (race condition?)
---------------------------------------------------------------
Key: JRUBY-5635
URL: http://jira.codehaus.org/browse/JRUBY-5635
Project: JRuby
Issue Type: Bug
Components: Embedding
Affects Versions: JRuby 1.6
Environment: OS X 10.6.6 (64-bit) and java 1.6.0_24
Reporter: Adam Murray
BACKGROUND
Even though JRuby 1.6 performance is supposedly better, I have found the
startup time for ScriptingContainer to be noticeably slower than JRuby 1.5.6,
especially when constructing a pool of ScriptingContainers at once. While
investigating this with some timing tests, I discovered more serious issues.
ISSUE SUMMARY
When instantiating a new ScriptingContainer and immediately calling put() to
set a variable, the variable will occasionally be undefined in the next
runScriptlet() call. Additionally, if you do this too many times you will
eventually crash the JVM with a java.lang.OutOfMemoryError. These behaviors are
regressions that I cannot reproduce in JRuby 1.5.6.
REPRODUCTION STEPS
Save this code as container_put_test.java and run it against JRuby 1.6.0
complete jar:
----------------------------
import org.jruby.embed.ScriptingContainer;
public class container_put_test {
public static void main(String[] args) {
for(int i = 0; i < 1000; i++) {
ScriptingContainer container = new ScriptingContainer();
container.put("$x", 0);
container.runScriptlet("puts $x");
}
}
}
----------------------------
You should see all 0s printed to the screen, but I occasionally see a nil.
If I change the i<1000 in the loop to i<10000, I consistently get a
java.lang.OutOfMemoryError with JRuby 1.6. The threshold at which this occurs
probably depends on your machine and JVM settings.
MORE DETAILS
To check the behavior with different variable types, I changed the loop to this:
for(int i = 0; i < 10000; i++) {
ScriptingContainer container = new ScriptingContainer();
container.put("message", "local variable");
container.put("@message", "instance variable");
container.put("$message", "global variable");
container.put("MESSAGE", "constant");
String script =
"puts message\n" +
"puts @message\n" +
"puts $message\n" +
"puts MESSAGE";
container.runScriptlet(script);
}
For this test, I sometimes get an undefined local/constant variable error, and
other times I get the following exception:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size:
2
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.remove(ArrayList.java:387)
at java.util.Collections$SynchronizedList.remove(Collections.java:1825)
at
org.jruby.embed.variable.VariableInterceptor.terminateLocalVariables(VariableInterceptor.java:237)
at
org.jruby.embed.internal.BiVariableMap.terminate(BiVariableMap.java:391)
at
org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:146)
at
org.jruby.embed.ScriptingContainer.runUnit(ScriptingContainer.java:1229)
at
org.jruby.embed.ScriptingContainer.runScriptlet(ScriptingContainer.java:1222)
at jruby_embed_perf.main(jruby_embed_perf.java:25)
As mentioned before, all these tests run flawlessly with JRuby 1.5.6.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email