Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP


#inspect goes into infinite loop #22

mperham opened this Issue · 13 comments

7 participants

Mike Perham Ben Langfeld Tony Arcieri Josh Adams Jonathan Rochkind Chuck Remes Tim Carey-Smith
Mike Perham

An actor that has an ivar to an object that contains a circular reference to the same actor will go into an infinite loop when #inspect is called on the actor.

Ben Langfeld

@tarcieri Do you have any thoughts on the way to approach the fix for this? I need to get it fixed within the next few days and would appreciate some pointers.

Mike Perham
Tony Arcieri

Short of that I don''t have a near-term solution, unfortunately. I need a recursion detection mechanism, and that won't be trivial. I've been mulling some sort of way to collect stack traces across actors. At the very least I need a UUID mechanism for call chains.

Ben Langfeld
Tony Arcieri

I added Celluloid.uuid that I'd like to be able to use to track "call chains", that is the flow of calls between actors. Each call chain will have a unique UUID.

If you know the UUID of every active call chain, it shouldn't be too hard to detect "recursion", or perhaps more aptly reentrant calls from the same call chain.

Josh Adams

:+1: I'm a total noob and this infinite loop is trivial to run into and caused me moderately sad grief. My load spiked to > 1000 on a core i5 in about 60 seconds

Tony Arcieri


The temporary workaround is to redefine "inspect" on one of the objects.

I have the rudiments of a permanent fix in place, but I have not yet wired them up

Tony Arcieri

In case anyone is wondering, this is still a known issue. I will try to get a fix into Celluloid 0.13

Jonathan Rochkind

Ruby stdlib Object#inspect avoids this with some kind of recursion detector. It may (or may not) be useful to look at how it does so as a model. It seems to use a C function 'rb_exec_recursive'. You may be well familiar with this and know exactly what ruby Object#inspect does and why it doesn't apply to celluloid, just didn't see it mentioned and got curious and went to look at the ruby stdlib code and behavior.

1.9.3p194 :001 > o =
 => #<Object:0x1f9dac> 
1.9.3p194 :002 > o.instance_variable_set("@foo", o)
 => #<Object:0x1f9dac @foo=#<Object:0x1f9dac ...>> 
1.9.3p194 :003 > o.inspect
 => "#<Object:0x1f9dac @foo=#<Object:0x1f9dac ...>>" 
Tony Arcieri

@jrochkind yeah, so I've been building the prerequisites for a recursion detector in Celluloid. All call chains are now tagged with a UUID, so in theory it's as simple as walking the task lists and see if another task for the same method name is participating in the same call chain as the current one (i.e. they have the same UUID).

Unfortunately there's not presently a way to inspect the call chain for a given task, although that information is being propagated throughout the system.

Chuck Remes

What's the recommended work around for now? Is it sufficient to define an #inspect method on actors in the system? Or do I need to redefine inspect on non-actor objects too?

Tony Arcieri

Redefine #inspect for actors pretty much. You might also confirm you're seeing a spike in CPU usage

Tony Arcieri tarcieri referenced this issue from a commit
Tony Arcieri tarcieri Detect recursion in #inspect (fixes #22)
This detects recursion between actors during #inspect and similates Ruby's own
behavior for representing circular object graphs, replacing duplicate instances
of the original actor in the inspect output with "...", e.g.:

    #<Celluloid::ActorProxy(Foo:0x3fe79ea577f4) @bar=#<Celluloid::ActorProxy(
    Bar:0x3fe79e0585b4) @foo=...>>

The above shows a cyclical relationship between the Foo and Bar classes.

Without this sort of detection #inspect goes into an infinite loop which can
be both confusing and infuriating to newcomers and the experienced alike,
myself included!
Tim Carey-Smith

I'm gonna close this as we have a solution in #250.

Tim Carey-Smith halorgium closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.