Project

General

Profile

Actions

Bug #18649

closed

Enumerable#first breaks out of the incorect block when across threads

Added by Eregon (Benoit Daloze) over 2 years ago. Updated over 2 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
[ruby-core:107980]

Description

def synchronize
  yield
end

def 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
      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 foo
  Thread.new do
    result = execute(-> { yield 42 })
    p [:result, result]
  end.join
end

p [:first, to_enum(:foo).first]

This code should raise LocalJumpError (and that should get rescue'd) because Enumerable#first can't break/return across threads.
But instead, it seems to break out of the block given to synchronize, which is clearly wrong.
That case is shown as :should_not_reach_here!.

Results:

ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux]
:before
:should_not_reach_here!
[:result, [true, nil, nil]]
[:first, 42]

ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x86_64-linux]
:before
:should_not_reach_here!
[:result, [true, nil, nil]]
[:first, 42]

CRuby (3.0 and 3.1) print :should_not_reach_here!, which is a semantic bug, if we get to the end of execute we should have gotten to the end of the block given to synchronize.

This is related to #18474 and https://github.com/ruby-concurrency/concurrent-ruby/issues/931.


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #18474: 938e027c seems to have caused a regression in yield handling with concurrent-rubyClosedActions
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0