Skip to content
This repository

#inspect goes into infinite loop #22

Closed
mperham opened this Issue January 29, 2012 · 13 comments

7 participants

Mike Perham Tim Carey-Smith Ben Langfeld Tony Arcieri Josh Adams Jonathan Rochkind Chuck Remes
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
Collaborator

@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
Owner

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
Collaborator
Tony Arcieri
Owner

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
Owner

:(

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
Owner

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.new
 => #<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
Owner

@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
Owner

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 May 12, 2013
Tony Arcieri 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!
2bee037
Tim Carey-Smith
Owner

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

Tim Carey-Smith halorgium closed this May 13, 2013
Ben Langfeld benlangfeld referenced this issue in adhearsion/adhearsion October 14, 2013
Closed

#inspect infinite loops #377

Ben Langfeld benlangfeld referenced this issue in adhearsion/adhearsion January 05, 2014
Closed

Infinite loop working with Call variables #416

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.