Projects

Ticket #511 (closed defect: fixed)

Opened 2 years ago

Last modified 21 months ago

GCD crash with indirect method access

Reported by: joshua.ballanco@… Owned by: lsansonetti@…
Priority: blocker Milestone: MacRuby 0.7
Component: MacRuby Keywords: GCD
Cc: darrin@…

Description (last modified by joshua.ballanco@…) (diff)

The following code will crash when I run it on my Mac Pro (8x2.26 GHz):

#!/usr/local/bin/macruby

class Foo
  def doit
  end
end

class Bar
  def initialize
    @foo = Foo.new
  end

  def step
    100.times{ @foo.doit }
  end
end

@bars = []
1000.times { @bars << Bar.new }

steps = Dispatch::Group.new
@bars.each do |bar|
  Dispatch::Queue.concurrent.async(steps) { bar.step }
end
steps.wait

Commenting out the "@foo.doit" line prevents the crash.

Change History

follow-up: ↓ 2   Changed 2 years ago by conradwt@…

The error is not produceable using r3126.

in reply to: ↑ 1   Changed 2 years ago by joshua.ballanco@…

Replying to conradwt@…:

The error is not produceable using r3126.

What is the machine you were testing on? This seems to be a race, and I've only verified that the above example crashes on the machine specified.

  Changed 2 years ago by lsansonetti@…

I can't reproduce the crash either on my mac book pro, but I suspect it might repro on a machine with more CPU cores like a Mac Pro.

  Changed 2 years ago by joshua.ballanco@…

  • description modified (diff)

Adding repetitions inside of "step" makes it crash more regularly.

  Changed 2 years ago by darrin@…

  • cc darrin@… added

Cc Me!

follow-up: ↓ 8   Changed 2 years ago by lsansonetti@…

Josh, can you try to reproduce the problem with r3272?

  Changed 2 years ago by ernest.prabhakar@…

  • cc ernest.prabhakar@… added

Cc Me!

in reply to: ↑ 6   Changed 2 years ago by joshua.ballanco@…

Replying to lsansonetti@…:

Josh, can you try to reproduce the problem with r3272?

Still reproducing...

  Changed 2 years ago by joshua.ballanco@…

A day of Yak shaving later, and it seems that the root cause is calling "invalidate_method_cache" as part of method resolution when another thread already has the cached method in use. As suggested by Laurent, first calling the methods once on the main thread fixes the issue:

class Foo
  def doit
    puts "hi there!"
  end
end

class Bar
  def initialize
    @foo = Foo.new
  end

  def step
    100.times{ @foo.doit }
  end
end

@bars = []
1000.times { @bars << Bar.new }
@bars.each(&:step)

steps = Dispatch::Group.new
@bars.each do |bar|
  Dispatch::Queue.concurrent.async(steps) { bar.step }
end
steps.wait

  Changed 2 years ago by ernest.prabhakar@…

  • cc ernest.prabhakar@… removed

Cc Me!

  Changed 21 months ago by joshua.ballanco@…

  • status changed from new to closed
  • resolution set to fixed
  • milestone set to MacRuby 0.7

Appears to be fixed as of r4182.

Note: See TracTickets for help on using tickets.