Here's an even simpler example. You don't need anything but the
following to demonstrate the problem.

class Foo
  Finalizer = lambda{}
  def initialize
    ObjectSpace.define_finalizer(self,Finalizer)
  end
end
def test
  10.times do
    GC.start
    count = ObjectSpace.each_object(Foo) {}
    p "Count: #{count}"
    Foo.new
  end
end
test # -> no leak
"Count: 0"
"Count: 1"
"Count: 2"
"Count: 2"
"Count: 2"
etc.

Now, re-open Foo and add an inline finalizer.

class Foo
  def initialize
    ObjectSpace.define_finalizer(self,lambda{})
  end
end
test # -> now it leaks
"Count: 1"
"Count: 2"
"Count: 3"
"Count: 4"
etc.

I realize the scope of the lambda invocation is different in this
example, but since the behavior is so similar, I thought it likely
pointed to the same underlying issue.

Dan

---
dev.zeraweb.com