diff --git a/ext/java/org/jruby/ext/psych/PsychParser.java b/ext/java/org/jruby/ext/psych/PsychParser.java index 472327b8..05374e38 100644 --- a/ext/java/org/jruby/ext/psych/PsychParser.java +++ b/ext/java/org/jruby/ext/psych/PsychParser.java @@ -236,6 +236,16 @@ private static StreamReader readerForString(ThreadContext context, RubyString st public IRubyObject parse(ThreadContext context, IRubyObject handler, IRubyObject yaml, IRubyObject path) { Ruby runtime = context.runtime; + // The parser calls back into Ruby for every event, so a handler can call + // Psych::Parser#parse again on the same object, which would replace the + // parser the loop below is still driving. + if (parsing) { + throw runtime.newRaiseException( + (RubyClass) runtime.getModule("Psych").getConstant("Exception"), + "parser is already parsing, it cannot be reused from a handler callback"); + } + parsing = true; + try { LoadSettings loadSettings = loadSettingsBuilder.build(); parser = new ParserImpl(loadSettings, new ScannerImpl(loadSettings, readerFor(context, yaml, loadSettings))); @@ -324,6 +334,8 @@ public IRubyObject parse(ThreadContext context, IRubyObject handler, IRubyObject } catch (Throwable t) { Helpers.throwException(t); return this; + } finally { + parsing = false; } return this; @@ -567,6 +579,7 @@ private LoadSettings buildSettings() { private Parser parser; private Event event; + private boolean parsing; private final LoadSettingsBuilder loadSettingsBuilder; private final CallSites sites; diff --git a/test/psych/test_parser.rb b/test/psych/test_parser.rb index aeb74244..4b0bd9bf 100644 --- a/test/psych/test_parser.rb +++ b/test/psych/test_parser.rb @@ -118,8 +118,6 @@ def event_location start_line, start_column, end_line, end_column end def test_parse_is_not_reentrant - pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/ - handler = ReentrantHandler.new handler.inner_yaml = "--- inner\n" parser = Psych::Parser.new handler @@ -139,8 +137,6 @@ def test_parse_is_not_reentrant end def test_parse_is_not_reentrant_with_invalid_inner_document - pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/ - handler = ReentrantHandler.new handler.inner_yaml = "--- \x00bad\n" parser = Psych::Parser.new handler