How do enterframe and timer interrupts work?

I have been wondering this for a while and need some clarification: 

I have this code:  

if (self.nextvx == nil ) then print ("nextvx is nil and shouldn't be ", self.myname, self.isRotating , self.isEaten , self.isDeleted ) else self:setdirection(self.image.x + self.nextvx , self.image.y + self.nextvy) end 

Every once in a blue moon I get an error saying that nextvx is nil and my code terminates.  So I am wondering just how this can ever happen given my IF stmt above.  

For simplicity’s sake I only have 2 events running my game. 

1.  enterframe 

2.  a timer that ticks off every 10th of a second.  

Is it possible for a timer event to get in between these 2 lines of code?  

In my enterframe loop I kick off some code.  What happens if my code doesn’t complete before the next enterframe is scheduled to run?  I assume lua is single threaded, is that true?  If true, how can enterframe  be called again if the previous code hasn’t completed?   Do you guys implement some kind of object lock to avoid interrupts messing with code currently running on an object? 

This happens so rarely that is has been impossible for me to track down this error.  However, if my game actually got popular I could see this happening all the time and with many bad reviews.  

the timer function is a Runtime-function like many others function that is called each frames.

For example, try :

local tim=timer.performWithDelay(1000, function() end,1) print( "tim = ".. tostring(tim) ) print( Runtime.\_tableListeners.enterFrame[1].\_runlist[1] ) \<-- same table as tim

So I think ( i am not sure ) that each frame, all functions on enterFrame is called one after an other. and if the specific function inside the timer is written in a way to interrupt the excecution of the others functions during one frame ( a theard ? ), the others functions can be affected.

@Laura,

Is it possible for a timer event to get in between these 2 lines of code?  

TL;DR - The short answer is, “No.”

As long as Corona is not multi-threaded (and I’m 99.99% sure it is not), then no script or (non-system) event may preempt an executing script.

Both enterFrame listeners and timers are queued for processing on the next available frame.

For enterFrame listeners this is every frame, for timers it depends on when the timer duration has ‘expired’.

Event Processing Queue(s)

I have not seen the internals of Corona, but I have coded a written two game engines (long ago) and if I were to hazard a guess, the way enterFrame, other event listeners, and timers are being handled can occur in one of three basic ways

First, let’s assume the engine/sdk has a game loop that does its best to execute tasks on a frame by frame basis, while maintaining forward progress and fairly consistent frame durations.  i.e. At 30 FPS, the average frame duration will be 33.33 ms.

Second (and this may be a simplification), let’s assume that each frame is broken into two major phases:

A. Rendering, Physics, and all other ‘internal’ stuff.

B. User defined event (listeners), timers, and other script handling.

Third, lets agree that Corona is single-threaded and if either phase A or phase B takes ‘too long’, then the frame duration average will be breached.  i.e. If there is too much work, a frame will take longer than 33.33 ms to complete.

Having assumed all of the above, there are three ways that phase B can be implemented:

  1. Each listener, timer, … category is bundled.

  2. All listeners, timers, handlers are homogeneously queued.

  3. A hybrid of 1 + 2

In case #1 (the most common implementation I’ve seen and the easiest to code), the engine/sdk iterates  over a fixed and immutably ordered list of tasks each frame.  That is, it handles all queued event listener, timers, etc by groups.

  • First it may handle all enterFrame listeners.

  • Second it may handle all collision handlers.

  • Third all touch handlers.

  • Fourth all timers,

  • etc…

In case #2, all event listeners, timers, etc are queued for handling based on when they are detected ‘ready to execute’ and the engine/sdk then iterates over a list like this:

  • timer 1

  • enterframe 1

  • enterframe 2

  • touch 1

  • timer 2

Some Things I Know For Sure

If the above is a little hand-wavy for you I apologize, but again I haven’t seen the internals of the engine.  That said I’ve done extensive exploratory work trying to answer this question in the past.  Things I do know:

  • Timers are ordered against each other.  i.e. If you schedule timer A then timer B with the same duration starting in the same frame, timer A will execute before timer B.
  • enterFrame - Similarly enterFrame listeners are ordered and consistent in the same way.
  • As far as I can tell, events are grouped, but I’m not 100% sure of the execution/handling order.

Your Example

In the example you gave, your:

  • enterFrame listener will execute every frame.
  • The timer will execute every 3rd or 4th frame if FPS is set to  30FPS.
  • The timer will NEVER suspend executing code.

Special Timer Times

Please note: There is are some things you need to be aware of with regards to timers and times used for them:

  • time == 100 - Your example, will execute approximately every 3rd or 4th frame when FPS set to 30. 
  • time == 1 - This is effectively saying, “execute this in the next frame”.
  • time == 0 - This is effectively saying, “execute this right now”.  (I have to double check this, but IIRC this was the outcome of my prior tests.)

Roaminggamer, 

    As always your replies are great.  However, it in no way explains how that line of code keeps getting executed.   So so sad. 

For now I put a lock on the object and only process new events for it when the lock is freed.   With 1.5 hours of testing so far the lock has never been hit.  Maybe it depends on sun spots for something.  My game doesn’t appear to be laggy unless I load it onto an kindle fire version 1.   So I am not sure I am approaching an enterframe queuing situation, if in fact Corona queues enterframe events. 

Again,  thanks for the insight.  you can only tell so much from reading the manuals.  Real world experience trumps book smarts any day.  

@laurasweet8888,
 
Sorry!  I’m so bad sometimes.  I get so carried away answering the question I want to answer that I don’t give proper help.
 
I can see basically what you’re trying to do, but tell me if I’m wrong…
 
You are trying to prevent the code from executing if the object is invalid right?
 
If so, there are two better approaches.
 

  1. If the object has a physics body do this:

    – A bit extreme, but will catch all invalid object cases with a body – if ( self and self.getLinearVelocity and type(self.getLinearVelocity) == “function” ) then self:setdirection(self.image.x + self.nextvx , self.image.y + self.nextvy) else print ("nextvx is nil and shouldn’t be ", self.myname, self.isRotating , self.isEaten , self.isDeleted ) end

  2. If the object does not have a physics body do this:

    – A bit extreme, but will catch all invalid object cases without a body – if ( self and self.removeSelf and type(self.removeSelf) == “function” ) then self:setdirection(self.image.x + self.nextvx , self.image.y + self.nextvy) else print ("nextvx is nil and shouldn’t be ", self.myname, self.isRotating , self.isEaten , self.isDeleted ) end

The Open Question

You also wondered ‘how can this be happening’.

When a display object is removed (with obj:removeSelf() or display.remove(obj))…

  • Corona strips off most of the bits it added to the object ( fields like x, y, etc. and functions like enterFrame, getLinearVelocity, etc.) 
  • Corona does not strip of functions and fields you have added.
  • Corona leaves behind a table ‘stub’  that has some fields and functions still attached.
  • Corona then passes a reference to that table to the garbage collector.
  • The stub won’t get collected till all references to the stub are cleared.

Thus, the stub can hang around for one or two frames after deletion.

If the stub is then passed to a listener or timer (which it looks like your code is part of), and if you manipulate Corona fields/functions in any way, you’ll get an error.

TWO POSTS - See answer above.  I think it will help you.

If you are trying to figure out WHY the object is becoming invalid, then I would suggest sharing the project with someone so they can peek directly at the code.

Better, if you can re-create this in a small example project, just zip it up and share it here.

I wish I could consistently re-create it.  It only happens once a month or so.  If I packaged something smaller I don’t see how you would ever hit it or know that the new package would even have the same error.  But thanks for the offer. 

To insulate myself from corona display objects stuff self in my example isn’t a display object.  I assign self.image the display/physics/listeners/transitions /etc…   So I could removeself all day against self.image and self.nextvx should still not be nil.  Actually, due to this bug nextvx is never ever nil from the time the object is created.  But you may be onto something with this garbage collection thing.  I do eventually destroy this object and delete it.   But maybe corona is slow getting all references of it from the displaygroup it is a part of.  Then on the next frame I process the objects in the displaygroup again and there is a half deleted half garbage collected one in there?  I bet that is it.   Since my code which does the delete on self  happens in real time self.nextvx is deleted and set to nil.   That has to be it.   So all I need to do is destroy the master object self  a second later after corona has a chance to catch up with what is going on.  My master object will be locked for that second so no further updates will happen to it anyway. 

Again,  I can’t thank you enough for helping me work out this bug that has been pestering me for quite a while now.     

If of course this all turns out to be true, I think this is a bug.  when I do a removeself() the object should be deleted from the displayGroup immediately.  

This is what I am doing now is there something I could do to ensure the object is removed immediately from the display Group without setting a time and running clear at a later time.  

--- Clears this object. function FF:clear() for k, v in pairs( self ) do -- print ("k is ", k ," value is ", v) if k ~= "image" and type( k ) ~= "function" then self[k] = nil end end end -- delete this object function FF:destroy() self.isEaten = true self.FGFgroup.currentcount = self.FGFgroup.currentcount - 1 if self.image.collision ~= nil then self.image:removeEventListener( "collision", collision\_fish ) end self.image:removeEventListener( "sprite", spritelistener ) transition.cancel(self.image) self:clear() self.image:removeSelf() -- delete Display Object and removes from DG self.image = nil self = nil return end

Please don’t get the impression that objects just hang around after being deleted.  They are deleted right away.  The problem is, references to them are not.

You can get into trouble if you delete an object that will be touched later in the same frame.

Let me give you a ‘for example’

  1. A new frame starts.

  2. Phase A executes and a number of collision listeners are queued for ‘handling’.

  3. Phase B begins and as the listeners are called, one after the other, a listener deletes a display object X.

  4. Phase B continues and later another listener is processed, but this listener tries to do something with object X.

At this point, if you don’t have safety code in place, the app will crash or at least complain loudly. :slight_smile:

Question

What is the  table of objects for?

If you are keeping objects in a table and iterating over that table, but don’t care about order, then you’re better off doing this:

local myStuff = {} local function finalize( self ) myStuff[self] = nil end local first for i = 1, 10 do local ball = display.newCircle( 10, 10, 10 ) myStuff[ball] = ball first = first or ball -- grab reference to first ball for example end display.remove(first) -- 'finalize' automatically called and reference to ball removed from table. for k,v in pairs(myStuff) do v.x = v.x + 10 end

I like to fool / convince myself that my code is tight enough that once the object is marked for deletion no amount of queued listeners can effect it because it is locked.  Hence, the isEaten flag.  

I can’t remember why I started using a table which describes the display object.  I remember a couple years ago trying to add something to the display object and I couldn’t figure out how so I went with the table wrapped around the display object as a work around.  Now I have objects that transform into other objects so the master object is not deleted.  I delete the display object or swap it with other ones.   Think of a guy turning into super guy and back again.  The master table holds all the fields that describe the object and the functions that make it go.  I also have objects that are made up of multiple display objects.  The master table keeps them all correctly ordered.  

I don’t have a master table of objects that are on the screen.  I just loop through a displayGroup and see what is there.  If it is there then I call code to make it do things.   So if the self.image.removeSelf() doesn’t actually remove the object immediately I think I can get into this strange case.  Now if it does then I am just chasing shadows.  For now I am going to just lock the master object table and schedule it to be deleted a few frames later and pray.   Something like this:  

--- Clears this object. function FF:clear() for k, v in pairs( self ) do if type( k ) ~= "function" then self[k] = nil end end return end function FF:clearnow() self:clear() self = nil return end -- delete this object function FF:destroy() self.isEaten = true self.FGFgroup.currentcount = self.FGFgroup.currentcount - 1 if self.image.collision ~= nil then self.image:removeEventListener( "collision", collision\_fish ) end self.image:removeEventListener( "sprite", spritelistener ) transition.cancel(self.image) self.image:removeSelf() -- delete Display Object and removes from DG local myClosure = function() return FF.clearnow( self ) end timer.performWithDelay( 350, myClosure , 1 ) -- self:clear() -- self = nil return end

Corona is easy they said, It is 10 times faster than native apps they said.   I think this stuff is plenty complex.  

I want to say this in the nicest way I can, but “You’re making it more complex than it needs to be.”

Until you’ve made half a dozen or more games (I mean small ones) and until you’ve learned to use Lua and Corona  you’re simply going to run into these issues.

If you find yourself needing to make a convoluted or complex solution to solve a problem that you think should be simple, stop and re-factor.  Focus on the problem you’re trying avoid and ask yourself why it needs to be avoided.  What is causing it?

Blasting through and trying to make a complicated game from zero or little experience will be very hard.

In this example, the use of a proxy object with a reference to the display object is troublesome to me.  It opens an avenue for object management problems.

I’d be interested in seeing your game’s code (if it isn’t terribly long), or at least I’d like to know what the game is about and does.  

Again, I feel like you’re over-complicating things.  This is natural and a side-effect of lack of experience with Lua and Corona. 

We solve the problems we understand with the tools we have at hand.

PS - How many games and sample programs have you made with with Corona prior to starting this project?

PPS - Coding games in Corona is a superior experience to native.  :slight_smile:

Preface: I am not trying to pick on you, but I see signs that things are going wrong for you in the code so I thought I’d point out a few things.


Hi.&nbsp; I am looking at your code post (your most recent one) and have some requests, questions, and suggestions.

<u><strong>Request</strong> </u>

When posting code, please convert all tabs to 3 spaces.&nbsp; This makes it easier to read in forums.&nbsp; Tabs are terrible in the code blocks here.&nbsp; :blink:

<u><strong>Question</strong></u>

When I look at this code:

    function FF:clear() for k, v in pairs( self ) do if type( k ) ~= "function" then self[k] = nil end end return end

I read it as:

- object ff has a method called clear()
- clear(), when called will iterate over every iterate-able field (Tip: not all fields will be iterated) and if the field <u><strong>name</strong></u>&nbsp;(the key k) is NOT a function then the reference will be cleared.

First, why are you trying to do this?

Second, this is wrong for (at least) two reasons:

1. As noted above, not all fields are iteratable so you will miss many.&nbsp; This is a weird thing and I can't exacltly explain it, but trust me you will miss all or most of the functions added by Corona.&nbsp; Only fields you added manually will iterate.
2. For this to work, you need to look at the type of the object the key is referring to, not the key.

     if type( v ) ~= "function" then self[k] = nil end

**This is one of those convoluted things that should make you stop and say... hmm why do I need to do this.**

<u><strong>No Need To Remove Local Listeners If...</strong></u>

I noticed in you remove the collision listener from and object.&nbsp; You don't need to do that if you're going to delete the object.

When you remove a display object ALL local listeners are automatically removed.&nbsp; i.e. If you added it like this:

    obj.touch = function( self, event ) end obj:addEventListener("touch")

It gets removed automatically when the object is deleteted.

<u><strong>Stopping Listeners Won't Stop Them From Being Called If They Are Queued</strong></u>

What?&nbsp;&nbsp;

What I'm saying is, if you try to stop listening for a "collision" listener on object X and object X is about the be processed for a collision, it will still get get called.

If the function is queued to be called in this frame it is going to be called no matter what you do. You need to handle this in the listener or prevent it from occurring at all through your design.&nbsp; (Tip: You can't always prevent this.)

<u><strong>No need to make a closure variable, and no need to 1 count. </strong></u>

This:

    timer.performWithDelay( 350, function() return FF.clearnow( self ) end )

is better than this:

    local closure = function() return FF.clearnow( self ) end timer.performWithDelay( 350, closure, 1 )

<u><strong>Dot dot dot dot... Equals Trouble</strong></u>

When I see code with lots of dots I know the developer is in trouble.&nbsp; To be fair, you're only two deep in this code, but it still smells of complicated and dangerous to me.

    self.FGFgroup.currentcount 

I was going to add some more notes... but an emergency came up over here and I have to jet.&nbsp; Sorry! :(

As always, good food for thought.  I am sure I am doing everything wrong.  I had never coded any game before this one.  So I am sure I am not doing things the best way.  some of my reasons are:  

1.  I have read over and over that if you don’t set variables to nil then they wont be garbage collected by lua.  That is why I was doing the clear.  Not sure why I am omitting the functions and now that you mention that I am omitting the functions incorrectly and they to are getting cleared so be it.  I guess they need to be cleared as well  :)      Is it true that if I just nil the parent of the table all the dot dot dot children will go away as well?   If that is true then I guess I don’t have to clear each field.   I have never had a lua class so I don’t know the answer to simple questions like this sadly.  

2.  As for the listeners I didn’t want them firing after the object was cleared.  That makes for errors a plenty.  I am sure at some point I got some error thrown at me so I just stuck that in there so they stop firing.  I bet I used a function listener once and that is why I got the error.  I guess I don’t need to do this for the table listeners.  But why not be thorough?   My thinking was if I created it I am deleting it.   

  1. I can get rid of the closure sure.  But to be fair.  Today I went to the corona web page which describes timer.performWithDelay and that is the example exactly as it was on the page.   As for letting it default to 1 instead of listing it?   Well what if someone changes the default to 9 in the next build?   You can’t be too careful.  

4.  I believe I have only added one more level of dots to the equation.  The master object which all the other stuff is a part of.  Otherwise, I would have had to add all these functions and fields directly to the display object.  I know you will hate this but some of my master objects inherit functions and fields from other master objects.  I have base fish functions FF.  special types of fish will use FF as the base and build on top of that so I don’t have to maintain mostly duplicate code for multiple types of fish.  The FGFgroup I created to implement schools of fish that swim together in patterns.  All the master objects in a school need to know which other ones are in their school.   As always, I am sure there was a much easier way to do things but I am just here with my dog and he doesn’t help much other than moral support.  

"What I’m saying is, if you try to stop listening for a “collision” listener on object X and object X is about the be processed for a collision, it will still get get called."

Now this is very interesting and important.  I could see this causing my problem.   Let’s say the enterframe queues my code and then a collision event is also queued.  I could see them firing back to back in just the right situations and the first one causing me to delete the master object.  Before, the dust settles the second event drives the code and something wasn’t completely cleaned up yet.  I can’t check for the master object to be locked because it is gone because it was just deleted.   Now as I type this I feel that if this situation happened I would get all sorts of strange errors and behavior.  But I have never seen any of that.   I have just seen the one case I described at the very top of the topic where I check for nil and the very next line the variable is nil.  That is one tight timing window.  

It seems that waiting 350 before deleting the master object should close this window.  But this assumes all my assumptions about what is going wrong are correct.   

Thanks again for the insight.  I know it takes a ton of time to help others and I really appreciate it.  

L

Answers to last post questions in order:
 
1. Yes, it is true.

local his = {} his.face = display.newCircle( 100, 100, 100 ) his.leye = display.newCircle( 80, 70, 10 ) his.reye = display.newCircle( 120, 70, 10 ) his.mouth = display.newLine( 70, 70, 140, 70) his.face:setfillColor( 0 ) his.leye:setfillColor( 0 ) his.reye:setfillColor( 0 ) his.mouth:setfillColor( 0 ) his.timer = function() for k,v in pairs( tmp ) do display.remove(v) end tmp = nil end timer.peformWithDelay( 1000, his )

  
One second later,  his face and face-parts is deleted…then all they all get garbage collected.  Ouch!

2. Sure it is OK to remove any listener you added, just so you know that for local event table listeners, they get removed automatically.

Runtime event listeners of all sorts must still be removed manually.

3. That will simply never happen and if it did, it would be a bug because someone changed the long-established API in a significant and unnecessary way.  :slight_smile:

4. The easiest way to protect yourself in this scenario is either to check for valid objects before operating on them, or far simpler add a flag to the object marking it valid or invalid.  Also, if you always add finalize listeners to clean up you’ll be golden.

For example:

local bob = display.newCircle( 100, 100, 100 ) -- The flag bob.isAlive = true function bob.enterFrame( self ) if( not self.isAlive ) then return end -- Do something to bob here end Runtime:addEventListener( "enterFrame", bob ) function bob.collision(self,event) if( not self.isAlive ) then return false end if( event.phase == "began" ) then self.isAlive = false display.remove(self) end return false end bob:addEventListener("collision") function bob.finalize(self) Runtime:removeEventListener("enterFrame",self) -- GOTTA DO THIS! self:removeEventListener("collision") -- DO NOT NEED TO DO; AUTOMATIC self:removeEventListener("finalize") -- DO NOT NEED TO DO; AUTOMATIC end bob:addEventListener("finalize")

Thanks,  you have explained how stuff works which is great.  I now have things to ponder.  

the timer function is a Runtime-function like many others function that is called each frames.

For example, try :

local tim=timer.performWithDelay(1000, function() end,1) print( "tim = ".. tostring(tim) ) print( Runtime.\_tableListeners.enterFrame[1].\_runlist[1] ) \<-- same table as tim

So I think ( i am not sure ) that each frame, all functions on enterFrame is called one after an other. and if the specific function inside the timer is written in a way to interrupt the excecution of the others functions during one frame ( a theard ? ), the others functions can be affected.

@Laura,

Is it possible for a timer event to get in between these 2 lines of code?  

TL;DR - The short answer is, “No.”

As long as Corona is not multi-threaded (and I’m 99.99% sure it is not), then no script or (non-system) event may preempt an executing script.

Both enterFrame listeners and timers are queued for processing on the next available frame.

For enterFrame listeners this is every frame, for timers it depends on when the timer duration has ‘expired’.

Event Processing Queue(s)

I have not seen the internals of Corona, but I have coded a written two game engines (long ago) and if I were to hazard a guess, the way enterFrame, other event listeners, and timers are being handled can occur in one of three basic ways

First, let’s assume the engine/sdk has a game loop that does its best to execute tasks on a frame by frame basis, while maintaining forward progress and fairly consistent frame durations.  i.e. At 30 FPS, the average frame duration will be 33.33 ms.

Second (and this may be a simplification), let’s assume that each frame is broken into two major phases:

A. Rendering, Physics, and all other ‘internal’ stuff.

B. User defined event (listeners), timers, and other script handling.

Third, lets agree that Corona is single-threaded and if either phase A or phase B takes ‘too long’, then the frame duration average will be breached.  i.e. If there is too much work, a frame will take longer than 33.33 ms to complete.

Having assumed all of the above, there are three ways that phase B can be implemented:

  1. Each listener, timer, … category is bundled.

  2. All listeners, timers, handlers are homogeneously queued.

  3. A hybrid of 1 + 2

In case #1 (the most common implementation I’ve seen and the easiest to code), the engine/sdk iterates  over a fixed and immutably ordered list of tasks each frame.  That is, it handles all queued event listener, timers, etc by groups.

  • First it may handle all enterFrame listeners.

  • Second it may handle all collision handlers.

  • Third all touch handlers.

  • Fourth all timers,

  • etc…

In case #2, all event listeners, timers, etc are queued for handling based on when they are detected ‘ready to execute’ and the engine/sdk then iterates over a list like this:

  • timer 1

  • enterframe 1

  • enterframe 2

  • touch 1

  • timer 2

Some Things I Know For Sure

If the above is a little hand-wavy for you I apologize, but again I haven’t seen the internals of the engine.  That said I’ve done extensive exploratory work trying to answer this question in the past.  Things I do know:

  • Timers are ordered against each other.  i.e. If you schedule timer A then timer B with the same duration starting in the same frame, timer A will execute before timer B.
  • enterFrame - Similarly enterFrame listeners are ordered and consistent in the same way.
  • As far as I can tell, events are grouped, but I’m not 100% sure of the execution/handling order.

Your Example

In the example you gave, your:

  • enterFrame listener will execute every frame.
  • The timer will execute every 3rd or 4th frame if FPS is set to  30FPS.
  • The timer will NEVER suspend executing code.

Special Timer Times

Please note: There is are some things you need to be aware of with regards to timers and times used for them:

  • time == 100 - Your example, will execute approximately every 3rd or 4th frame when FPS set to 30. 
  • time == 1 - This is effectively saying, “execute this in the next frame”.
  • time == 0 - This is effectively saying, “execute this right now”.  (I have to double check this, but IIRC this was the outcome of my prior tests.)

Roaminggamer, 

    As always your replies are great.  However, it in no way explains how that line of code keeps getting executed.   So so sad. 

For now I put a lock on the object and only process new events for it when the lock is freed.   With 1.5 hours of testing so far the lock has never been hit.  Maybe it depends on sun spots for something.  My game doesn’t appear to be laggy unless I load it onto an kindle fire version 1.   So I am not sure I am approaching an enterframe queuing situation, if in fact Corona queues enterframe events. 

Again,  thanks for the insight.  you can only tell so much from reading the manuals.  Real world experience trumps book smarts any day.  

@laurasweet8888,
 
Sorry!  I’m so bad sometimes.  I get so carried away answering the question I want to answer that I don’t give proper help.
 
I can see basically what you’re trying to do, but tell me if I’m wrong…
 
You are trying to prevent the code from executing if the object is invalid right?
 
If so, there are two better approaches.
 

  1. If the object has a physics body do this:

    – A bit extreme, but will catch all invalid object cases with a body – if ( self and self.getLinearVelocity and type(self.getLinearVelocity) == “function” ) then self:setdirection(self.image.x + self.nextvx , self.image.y + self.nextvy) else print ("nextvx is nil and shouldn’t be ", self.myname, self.isRotating , self.isEaten , self.isDeleted ) end

  2. If the object does not have a physics body do this:

    – A bit extreme, but will catch all invalid object cases without a body – if ( self and self.removeSelf and type(self.removeSelf) == “function” ) then self:setdirection(self.image.x + self.nextvx , self.image.y + self.nextvy) else print ("nextvx is nil and shouldn’t be ", self.myname, self.isRotating , self.isEaten , self.isDeleted ) end

The Open Question

You also wondered ‘how can this be happening’.

When a display object is removed (with obj:removeSelf() or display.remove(obj))…

  • Corona strips off most of the bits it added to the object ( fields like x, y, etc. and functions like enterFrame, getLinearVelocity, etc.) 
  • Corona does not strip of functions and fields you have added.
  • Corona leaves behind a table ‘stub’  that has some fields and functions still attached.
  • Corona then passes a reference to that table to the garbage collector.
  • The stub won’t get collected till all references to the stub are cleared.

Thus, the stub can hang around for one or two frames after deletion.

If the stub is then passed to a listener or timer (which it looks like your code is part of), and if you manipulate Corona fields/functions in any way, you’ll get an error.

TWO POSTS - See answer above.  I think it will help you.

If you are trying to figure out WHY the object is becoming invalid, then I would suggest sharing the project with someone so they can peek directly at the code.

Better, if you can re-create this in a small example project, just zip it up and share it here.

I wish I could consistently re-create it.  It only happens once a month or so.  If I packaged something smaller I don’t see how you would ever hit it or know that the new package would even have the same error.  But thanks for the offer. 

To insulate myself from corona display objects stuff self in my example isn’t a display object.  I assign self.image the display/physics/listeners/transitions /etc…   So I could removeself all day against self.image and self.nextvx should still not be nil.  Actually, due to this bug nextvx is never ever nil from the time the object is created.  But you may be onto something with this garbage collection thing.  I do eventually destroy this object and delete it.   But maybe corona is slow getting all references of it from the displaygroup it is a part of.  Then on the next frame I process the objects in the displaygroup again and there is a half deleted half garbage collected one in there?  I bet that is it.   Since my code which does the delete on self  happens in real time self.nextvx is deleted and set to nil.   That has to be it.   So all I need to do is destroy the master object self  a second later after corona has a chance to catch up with what is going on.  My master object will be locked for that second so no further updates will happen to it anyway. 

Again,  I can’t thank you enough for helping me work out this bug that has been pestering me for quite a while now.     

If of course this all turns out to be true, I think this is a bug.  when I do a removeself() the object should be deleted from the displayGroup immediately.  

This is what I am doing now is there something I could do to ensure the object is removed immediately from the display Group without setting a time and running clear at a later time.  

--- Clears this object. function FF:clear() for k, v in pairs( self ) do -- print ("k is ", k ," value is ", v) if k ~= "image" and type( k ) ~= "function" then self[k] = nil end end end -- delete this object function FF:destroy() self.isEaten = true self.FGFgroup.currentcount = self.FGFgroup.currentcount - 1 if self.image.collision ~= nil then self.image:removeEventListener( "collision", collision\_fish ) end self.image:removeEventListener( "sprite", spritelistener ) transition.cancel(self.image) self:clear() self.image:removeSelf() -- delete Display Object and removes from DG self.image = nil self = nil return end