summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <[email protected]>2022-03-22 16:36:16 -0700
committerJeremy Evans <[email protected]>2022-04-21 20:48:27 -0700
commit4b14b2902abaa0e8f0d1e8282d2322f47431fa3f (patch)
tree086716257ae8dc7b4f0e5b928348648be3c9a57e
parent3fa768c5c308b61677342fe2caa9c54fe3a2c3c9 (diff)
Uncomment code to raise LocalJumpError for yield across thread through enum
Not sure if this is the correct fix. It does raise LocalJumpError in the yielding thread as you would expect, but the value yielded to the calling thread is still yielded without an exception. Fixes [Bug #18649]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5692
-rw-r--r--test/ruby/test_thread.rb55
-rw-r--r--vm.c2
2 files changed, 55 insertions, 2 deletions
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index e80ca16022..ddb4516b3c 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -1338,6 +1338,61 @@ q.pop
t.join
end
+ def test_yield_across_thread_through_enum
+ bug18649 = '[ruby-core:107980] [Bug #18649]'
+ @log = []
+
+ def self.p(arg)
+ @log << arg
+ end
+
+ def self.synchronize
+ yield
+ end
+
+ def self.execute(task)
+ success = true
+ value = reason = nil
+ end_sync = false
+
+ synchronize do
+ begin
+ p :before
+ value = task.call
+ p :never_reached
+ success = true
+ rescue StandardError => ex
+ ex = ex.class
+ p [:rescue, ex]
+ reason = ex
+ success = false
+ end
+
+ end_sync = true
+ p :end_sync
+ end
+
+ p :should_not_reach_here! unless end_sync
+ [success, value, reason]
+ end
+
+ def self.foo
+ Thread.new do
+ result = execute(-> { yield 42 })
+ p [:result, result]
+ end.join
+ end
+
+ value = to_enum(:foo).first
+ expected = [:before,
+ [:rescue, LocalJumpError],
+ :end_sync,
+ [:result, [false, nil, LocalJumpError]]]
+
+ assert_equal(expected, @log, bug18649)
+ assert_equal(42, value, bug18649)
+ end
+
def test_thread_setname_in_initialize
bug12290 = '[ruby-core:74963] [Bug #12290]'
c = Class.new(Thread) {def initialize() self.name = "foo"; super; end}
diff --git a/vm.c b/vm.c
index b8df0d6ee5..f5016f6dec 100644
--- a/vm.c
+++ b/vm.c
@@ -1806,11 +1806,9 @@ vm_iter_break(rb_execution_context_t *ec, VALUE val)
const VALUE *ep = VM_CF_PREV_EP(cfp);
const rb_control_frame_t *target_cfp = rb_vm_search_cf_from_ep(ec, cfp, ep);
-#if 0 /* raise LocalJumpError */
if (!target_cfp) {
rb_vm_localjump_error("unexpected break", val, TAG_BREAK);
}
-#endif
ec->errinfo = (VALUE)THROW_DATA_NEW(val, target_cfp, TAG_BREAK);
EC_JUMP_TAG(ec, TAG_BREAK);