System stack error in ObjectSpace.each_object

Hey guys, I'm just starting to mess around with metaprogramming in Ruby,
so I was just having a bit of fun and trying to make a script that would
allow for creating a 'leader' object in a class, and then when that
object is sent a message, all other objects of some subordinate class
would respond to the same message.

So the script I wrote is here:
https://github.com/luke-gru/lemmings/blob/master/leader.rb

On line 52, I ran into this issue:

  def get_other_objects(subord_class)
    obj_ary = []
    ObjectSpace.each_object(subord_class) do |o|
      obj_ary.push(o) unless o.leader # here
    end
    obj_ary
  end

If I don't have the 'unless o.leader' expression modifier, it pushes
like a million of the 'leader' objects and raises a SystemStackError.

I have no idea why, and would really appreciate an answer.

Thanks,

-Luke

···

--
Posted via http://www.ruby-forum.com/.

When I ran your script, I didn't get that error. I got this output:

Test
true
#<Test:0x0ac544>
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys
hey guys

#<Test:0x0ac7ec> jumps: 'look at me!'

#<Test:0x0ac5bc> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac60c> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac620> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac634> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac65c> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac6c0> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac710> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac738> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac74c> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac760> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac788> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac7ec> jumps: 'Ahhhhhhhhh!'
#<Test:0x0ac544> jumps: 'Ahhhhhhhhh!'

#<Test:0x0ac7ec>
#<Test:0x0ac788>
ouch
ouch
ouch
ouch
ouch
ouch
ouch
ouch
ouch
ouch
ouch
ouch

Typically, SystemStackError is due to recursing for too long, perhaps I have
more memory than you, or perhaps the Ruby I'm using (1.9.2-p180) is less
memory intensive than the one you're using. Anyway, it should give you a
message with more information and a stack trace / line number that tells you
where to begin looking.

···

On Sun, Jul 31, 2011 at 4:29 PM, luke gruber <luke.gru@gmail.com> wrote:

Hey guys, I'm just starting to mess around with metaprogramming in Ruby,
so I was just having a bit of fun and trying to make a script that would
allow for creating a 'leader' object in a class, and then when that
object is sent a message, all other objects of some subordinate class
would respond to the same message.

So the script I wrote is here:
https://github.com/luke-gru/lemmings/blob/master/leader.rb

On line 52, I ran into this issue:

def get_other_objects(subord_class)
   obj_ary =
   ObjectSpace.each_object(subord_class) do |o|
     obj_ary.push(o) unless o.leader # here
   end
   obj_ary
end

If I don't have the 'unless o.leader' expression modifier, it pushes
like a million of the 'leader' objects and raises a SystemStackError.

I have no idea why, and would really appreciate an answer.

Thanks,

-Luke

--
Posted via http://www.ruby-forum.com/\.

Typically, SystemStackError is due to recursing for too long, perhaps I
have
more memory than you, or perhaps the Ruby I'm using (1.9.2-p180) is less
memory intensive than the one you're using.

Yeah, I'm running the same Ruby version and I have 4 gb of ram, not sure
why I get this error. Just to be sure, the script in the file
(unmodified) gives me no errors, but when I remove 'unless o.leader' on
line 51, that's when I run into this problem.

Anyway, thanks for checking.

-Luke

···

--
Posted via http://www.ruby-forum.com/\.

I can reproduce

...
/c/Temp/leader.rb:41:in `each'
/c/Temp/leader.rb:41:in `block (4 levels) in show_leadership'
/c/Temp/leader.rb:41:in `block (3 levels) in show_leadership'
/c/Temp/leader.rb:41:in `each'
/c/Temp/leader.rb:41:in `block (4 levels) in show_leadership'

[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

Aborted (core dumped)
09:05:22 ~$ ruby19 -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [i386-cygwin]

I assume you created some weird kind of recursion via
define_finalizer. I'm not really sure what's going on. Can you
explain what your code is supposed to do?

Kind regards

robert

···

On Mon, Aug 1, 2011 at 3:56 AM, luke gruber <luke.gru@gmail.com> wrote:

Typically, SystemStackError is due to recursing for too long, perhaps I
have
more memory than you, or perhaps the Ruby I'm using (1.9.2-p180) is less
memory intensive than the one you're using.

Yeah, I'm running the same Ruby version and I have 4 gb of ram, not sure
why I get this error. Just to be sure, the script in the file
(unmodified) gives me no errors, but when I remove 'unless o.leader' on
line 51, that's when I run into this problem.

Anyway, thanks for checking.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

This looks to me like an abuse of ObjectSpace.

If you need to keep track of all the objects of class Foo, then it would
be better to make some sort of container which keeps track of them
explicitly.

ObjectSpace is (a) inefficient, because it scans *every* object in the
system, and (b) unreliable, because it may show you objects which should
have died, but some reference is being held somewhere.

ObjectSpace is really just a debugging tool.

Also, finalizers are also extremely difficult to work with. There is
almost never a good case for using them. You should consider them part
of the internals of ruby (so that, for example, when an IO object gets
garbage-collected then the underlying file descriptor gets closed)

Regards,

Brian.

···

--
Posted via http://www.ruby-forum.com/.

I assume you created some weird kind of recursion via
define_finalizer. I'm not really sure what's going on. Can you
explain what your code is supposed to do?

robert

Yeah, it was just for fun and to learn some of these metaprogramming
methods, but what I was meaning to do was to be able to make a 'leader'
object of, say, class Foo. Upon choosing the leader object, you have to
choose a subordinate class to lead (which could be the same class as the
leader object, ie: Foo.

Basically the implementation was to take all the objects of the
subordinate class, then override all of the instance methods in the
leader object's class by putting new methods in the leader's singleton
class with the same name as the instance methods in the leader's class.
Every time these new 'leader' methods are called (ie: the leader
responds to a method that's defined in the leader's own class), it sends
the same method (with the same args &block) to all the subordinate
objects.

Anyway, I'm just having fun and I know playing with ObjectSpace can lead
to some weird errors, but this error seems to be consistent enough in
that I kept on running into it until I added that statement modifier.

Thanks for checking it out.

···

===========================
1)

If you need to keep track of all the objects of class Foo, then it would
be better to make some sort of container which keeps track of them
explicitly.

2)

ObjectSpace is (a) inefficient, because it scans *every* object in the
system, and (b) unreliable, because it may show you objects which should
have died, but some reference is being held somewhere.

Brian.

1) For the container idea, how would you go about doing this?
2) As for ObjectSpace returning dead objects, is there a way to force GC
during runtime? Also, does taking all variables that point to an object
and pointing them to nil effectively dangle an object like this?

Thanks Robert and Brian,

-Luke

--
Posted via http://www.ruby-forum.com/\.

In the initialize (or new) method of Foo, store self in a container
(an array on Foo, or another class).
But take into account that this means that all instances of Foo will
have an alive reference, so they will never be garbage collected.
Something like:

ruby-1.8.7-p334 :003 > class FooCollection
ruby-1.8.7-p334 :004?> class << self
ruby-1.8.7-p334 :005?> attr_reader :collection
ruby-1.8.7-p334 :006?> def << item
ruby-1.8.7-p334 :007?> (@collection ||= ) << item
ruby-1.8.7-p334 :008?> end
ruby-1.8.7-p334 :009?> end
ruby-1.8.7-p334 :010?> end
=> nil
ruby-1.8.7-p334 :015 > class Foo
ruby-1.8.7-p334 :016?> def initialize
ruby-1.8.7-p334 :017?> FooCollection << self
ruby-1.8.7-p334 :018?> end
ruby-1.8.7-p334 :019?> end
=> nil
ruby-1.8.7-p334 :020 > a = Foo.new
=> #<Foo:0xb70d9c80>
ruby-1.8.7-p334 :021 > b = Foo.new
=> #<Foo:0xb70d7dcc>
ruby-1.8.7-p334 :022 > FooCollection
=> FooCollection
ruby-1.8.7-p334 :023 > FooCollection.collection
=> [#<Foo:0xb70d9c80>, #<Foo:0xb70d7dcc>]

Take note that even if a and b go out of scope, the Foo instances they
referenced will never be GCed, because they are referenced by the
FooCollection.collection array.

Jesus.

···

On Tue, Aug 2, 2011 at 3:12 AM, luke gruber <luke.gru@gmail.com> wrote:

1) For the container idea, how would you go about doing this?

luke gruber wrote in post #1014312:

I assume you created some weird kind of recursion via
define_finalizer. I'm not really sure what's going on. Can you
explain what your code is supposed to do?

Yeah, it was just for fun and to learn some of these metaprogramming
methods, but what I was meaning to do was to be able to make a 'leader'
object of, say, class Foo. Upon choosing the leader object, you have to
choose a subordinate class to lead (which could be the same class as the
leader object, ie: Foo.

Basically the implementation was to take all the objects of the
subordinate class, then override all of the instance methods in the
leader object's class by putting new methods in the leader's singleton
class with the same name as the instance methods in the leader's class.
Every time these new 'leader' methods are called (ie: the leader
responds to a method that's defined in the leader's own class), it sends
the same method (with the same args &block) to all the subordinate
objects.

Not sure what this is supposed to do but I would always make the
connection between those objects explicit. And I would separate the
leading from determining the set of instances to lead. Here's one way

class Leader < BasicObject
  def lead(source)
    @objs = source
  end

  def method_missing(*a,&b)
    @objs.map {|o| o.send(*a,&b)}
  end
end

class Module
  Source = Struct.new :cl do
    include Enumerable

    def each(&b)
      return to_enum(:each) unless b
      ObjectSpace.each_object(cl, &b)
      self
    end
  end

  def lemmings
    Source.new self
  end
end

l = Leader.new
l.lead Hash.lemmings

p l.size

Kind regards

robert

···

--
Posted via http://www.ruby-forum.com/\.

luke gruber wrote in post #1014312:

1) For the container idea, how would you go about doing this?

Others have answered this already. (There's weakref if you really need a
container which doesn't prevent garbage collection, but I've never had
to use it)

2) As for ObjectSpace returning dead objects, is there a way to force GC
during runtime?

You can force garbage collection, but the issue is rather that the
garbage collector is conservative; any bit of junk sitting on the stack
which looks like it *might* be a reference to an object is treated as if
it is, just to be on the safe side. This means that some objects which
really could be garbage-collected, aren't.

You can write some simple test programs using ObjectSpace to count the
number of objects of each class, create some and drop the refs, then run
GC.start, then count them again. It's not unusual to see one or two
objects left in a particular class, even though there are no live refs.

Also, does taking all variables that point to an object
and pointing them to nil effectively dangle an object like this?

Explicitly destroying all references to an object will normally make it
eligible for garbage collection: it's a mark-and-sweep collector, so the
object won't be found during the mark phase. But as I say, a few objects
may be considered live when technically they aren't.

···

--
Posted via http://www.ruby-forum.com/\.

Something like:
ruby-1.8.7-p334 :003 > class FooCollection

Jesus.

That's cool, I like the way the class is effectively just that, a set
that's keeping track of the objects.

Thanks.

I would separate the leading from determining the set of instances to lead.

robert

I don't quite understand your example code.

class Module
Source = Struct.new :cl do
   include Enumerable

   def each(&b)
     return to_enum(:each) unless b
     ObjectSpace.each_object(cl, &b)

ObjectSpace.each_object takes, as its first argument, a module. I
thought
:cl was an instance variable of instances of the Source class. I don't
know much about structs, so I'd love an explanation.

Thanks Robert.

And Bryan, thanks for the explanations. I checked out weakref and it
looks
kinda cool. Although, yeah, can't imagine using it.

-Luke

···

--
Posted via http://www.ruby-forum.com/\.

I would separate the leading from determining the set of instances to lead.

I don't quite understand your example code.

There are two parts:

1. The method call propagation is done by instances of class Leader
which inherits BasicObject in order to have the minimum set of
predefined methods. A Leader takes an Enumerable as source for
instances to delegate to, which means you can stuff in anything which
is Enumerable (e.g. Array, Set).

2. Then I created a class Source which is also Enumerable and happens
to look into ObjectSpace whenever someone wants to iterate via #each.
So, ObjectSpace would be only one way to look for instances.

class Module
Source = Struct.new :cl do
include Enumerable

def each(&b)
return to_enum(:each) unless b
ObjectSpace.each_object(cl, &b)

ObjectSpace.each_object takes, as its first argument, a module.

... or a class. Correct.

I thought
:cl was an instance variable of instances of the Source class. I don't
know much about structs, so I'd love an explanation.

In the example "cl" is a member of the Struct which means there is a
pair of accessor methods, so "cl" really is a call to the getter. And
the getter is set to "self" in Module#lemmings (which is an instance
method of all modules and classes).

Struct is really a handy way to quickly create a class with a few
properties which also gives you #hash and #eql?. You can read more at
http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html

Kind regards

robert

···

On Wed, Aug 3, 2011 at 3:54 AM, luke gruber <luke.gru@gmail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

There are two parts:

In the example "cl" is a member of the Struct which means there is a
pair of accessor methods, so "cl" really is a call to the getter. And
the getter is set to "self" in Module#lemmings (which is an instance
method of all modules and classes).

robert

I'm an idiot, I just forgot that instance methods defined in class
Module are effectively singleton methods for all classes and modules (or
if they aren't, please let me know!).

Another question: is there a reason you explicity include enumerable,
because I think structs include enumerable by default?

Also, the members getter of a struct is set to 'self' by default?

Thanks again, I'm gonna look into your blog post.

-Luke

···

--
Posted via http://www.ruby-forum.com/\.

I read your post, Structs now make MUCH more sense, thanks. Should

have read before I posted above.

class Module
Source = Struct.new :cl do

So this is effectively creating a Source class that inherits from class
Struct and takes one argument to its constructor (initialize method)...

But my question still stands on whether or not the 'include Enumerable'
was just for clarification and to be explicit, because unless I'm wrong
class Struct includes Enumerable and Source is a child of class Struct,
inheriting #each.

Thanks for your patience, your blog looks like it's full of info. I've
gotta catch up on all the holes in my Ruby knowledge :slight_smile:

-Luke

···

--
Posted via http://www.ruby-forum.com/\.

I read your post, Structs now make MUCH more sense, thanks. Should

have read before I posted above.

class Module
Source = Struct.new :cl do

So this is effectively creating a Source class that inherits from class
Struct and takes one argument to its constructor (initialize method)...

Plus, you will have one pair of accessors for "cl" and a few more
things (e.g. access via like for a Hash).

But my question still stands on whether or not the 'include Enumerable'
was just for clarification and to be explicit, because unless I'm wrong
class Struct includes Enumerable and Source is a child of class Struct,
inheriting #each.

You're absolutely right. I wanted to make it explicit but of course
it's superfluous in this case. Should have added a comment. Sorry
for the confusion.

Thanks for your patience, your blog looks like it's full of info. I've
gotta catch up on all the holes in my Ruby knowledge :slight_smile:

Thank you for the feedback! And I need to catch up writing... Oh well.

Kind regards

robert

···

On Wed, Aug 3, 2011 at 11:43 PM, luke gruber <luke.gru@gmail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/