LocalJumpError raised on break from custom Enumerator enumeration #1270
I have little to no experience with JRuby, so it's possible I'm doing this wrong, but while I was working to make a library I'm developing JRuby compatible, I ran into some weirdness with the Enumerator class.
Long story short, breaking from a custom Enumerator raises "LocalJumpError: break from proc-closure". This same behavior is not observed when breaking from an enumerator obtained via Range#to_enum. I understand this may be related to how the enumerator is created by Range, so I would be open to suggestions on how I might refactor the code below to support break.
I looked through the specs and came across TestIterator#test_ljump which made it seem that a LJE when breaking from a block may be the desired behavior. However, the same spec also makes it seem like a break from a lambda should not raise a LJE. To this end I also tried building an Enumerator using a lambda to determine if that fixed the issue, however a LJE is still raised, though with a different message.
Here is some code I wrote up to demonstrate this issue. This same code does not raise an error when run against MRI 1.9.3 or 2.0.0. However for JRuby, I found this code raises a LJE in both 1.9 and 2.0 mode of JRuby 1.7.6 and 1.7.8. I'm running Ubuntu 12.04 and I've included full
Please let me know if I can answer any questions or provide any additional information!
The text was updated successfully, but these errors were encountered:
This is indeed a bug! It won't make it into 1.7.9 but I will mark it for 1.7.10 and we should see what we can do with it.
Work noting is that it fails the same with 1.7.4, which had our first Enumerator implementation, so it's not a regression in 1.7.5 and later (which have a new Enumerator impl).
Definitely should be fixed. Thank you for the reproduction!
The old logic here was turning all breaks that pass through an escaped proc into LongJumpError, even if they originated in a different frame/proc that could still validly handle the break. This commit modifies the logic to ignore the exception altogether (re-throwing it) if it is not associated with this proc/frame (by checking jumpTarget). Fixes #1270
Fixes #1270 on master.
Ok, we have fixes for this on 1.7 and master.
There's one caveat for 1.7: if an "escaped" proc (like the Enumerator block in the original example) and a separate block's break appear within the same method body (as in the one-liner version of the spec added to master), JRuby 1.7 can't tell that the break is intended for the outer block rather than the inner one. In that case, it will still prematurely turn the jump into a LocalJumpError. We may look at a fix for this in the future, but it's an obscure and uncommon case.
JRuby master (9k) is able to handle all cases correctly.
#2736 had a similar problem but it solves both issues on master. Basically, marking generator as a LAMBDA was confusing our nonlocal flow logic thinking we had a hard (method) scope so we would dump out in generator instead of the intended scope. Changed to a PROC.