Page 1 of 1

Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 5:25 am
by PrinceOfFunky
I have this check inside Timer function (Timer is set to 0.01, but this problem occurs with a low rate too):

Code: Select all

if (Owner != none) {
			Log(0@Owner);
			SetLocation(Owner.Location);
			SetRotation(Owner.Rotation);
			Log(1@Owner);
These are the logs when a pawn dies and becomes None:

Code: Select all

ScriptLog: 0 Autoplay.TMale0
ScriptWarning: ...Timer:003B) Accessed None
ScriptLog: 1 None
The code is longer than it, there are many instructions that need the pawn to not to be None. Should I seriously need to do the check on every line that requires the Owner?

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 5:35 am
by Higor
In UT's native c++ the game would insta-GPF, yes, you do need sanity checks when there's uncertainty that a reference will remain the same.

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 6:08 am
by Barbie
Does this mean that during Timer() execution other code is running that might change the references? AFAIK this can happen only in latent functions or multi threaded code.

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 6:09 am
by sektor2111
PrinceOfFunky wrote:These are the logs when a pawn dies and becomes None:
And then this thing will lose owner (I'm guessing) and then it might be going in destruction being NONE itself and without owner. And error is probably similar to GuidedWarshell problem when it's still rendering in Deletion process... Keep in mind that I have solved DynAI mod crash by adding a stupid check like this <If (Something != None && !Something.bDeleteMe)> and was the only way to not crash by trying to setup a thing which did not lived any longer (for some reason of that map).

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 6:10 am
by PrinceOfFunky
Higor wrote:In UT's native c++ the game would insta-GPF, yes, you do need sanity checks when there's uncertainty that a reference will remain the same.
So it is a prevention, well, thanks for the explanation :)
(To your knowledge, is this instantaneous prevention common in many softwares, other than UT?)

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 6:49 am
by Higor
As a matter of fact, the ONLY reason your reference is actually being set to none is because some other code in the same thread the game is running has nulled it.

I said it would GPF is you attempted to operate it on c++ without a sanity check, nothing more.
If this 'other code' wasn't setting your reference to none, even the unrealscript counterpart would GPF.

If you deallocate memory, any pointers to that memory region won't be nulled out.
So when memory has to be deallocated, either set the pointers to NULL (before, during or after deallocation) or simply destroy the pointer variables as well.


The game automatically deallocates actors after you pile up at least 256 (i think) destroyed actors and this only happens between ticks, not in the middle of it.
The process consists on running through the entire actor list, looping through Object/Actor variable types (defined in unrealscript), evaluating that there's a pointer to an actor and then seeing if this actor has bDeleteMe=True
If this actor has bDeleteMe=True, then the pointer is nulled (set=none).
Once all pointers to destoyed actors are nulled, the game will free up the object table and start deallocating memory.

Also, never, ever reference actors from outside the level unless you know how to prevent the garbage collector from crashing, or you know how to detect level switches before attempting to access an actor in a level that no longer exists.
Horrible examples of this is the Nexgen controller that references Nexgen actors from it's UWindow interface.
Another horrible example is ScriptedTexture class, in some cases a bit of mishandling will crash the game if the actor in charge of controlling a texture is destroyed and the NotifyActor variable isn't nulled out before level switch.

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 4:58 pm
by sektor2111
Info saved.
As another matter of fact I'll show you some of my crash code NONE related and... solution. It's a function called in PreBeginPlay

Code: Select all

			Dt = Spawn( class'DecoTest',Pn,,Pn.Location+Vect(0,0,1) );
			if ( Dt != None )
			{
//				log ( Self@"spawned"@Dt@"addressing to check"@Pn );
				if ( Dt.Location.X == Pn.Location.X
					&& Dt.Location.Y == Pn.Location.Y
						&& ( Dt.Location.Z - Pn.Location.Z == 1)
							&& !Dt.bDeleteMe ) //02-16-2016 #1 #2 - Now is no longer crashing
				{
//					log (Dt@"is good...");
					Dt.bHaveAGood = True; //#1 Accessed None - it is just in deletion process right after spawn for some reason, hell knows...
					Dt.Tag = 'MeMoving'; //#2 The same crap
					NumOps++;
				}
In previous session it crashed at some strange map without deletion check but... It was initially <!= None>. At this time is part of my playground with no crashes using snippet above.

Re: Code concurrence problem with Timer and None check

Posted: Wed Sep 28, 2016 8:08 pm
by Wormbo
Barbie wrote:Does this mean that during Timer() execution other code is running that might change the references? AFAIK this can happen only in latent functions or multi threaded code.
That particular Timer code actually calls that other code indirectly through SetLocation. Changing the location of an actor can immediately cause multiple events to happen, which in this case either just changed the Owner or even destroyed it. The following call to SetRotation then attempted to access a property of the now-empty Owner variable, causing the Accessed None error.

Re: Code concurrence problem with Timer and None check

Posted: Thu Sep 29, 2016 2:34 am
by PrinceOfFunky
Wormbo wrote:That particular Timer code actually calls that other code indirectly through SetLocation.
To me, it occurred using:
- SetLocation()
- SetRotation()
- Casting.
- IsA()
- Variables assignments.
- Variables retrievings.
- getStateName()
Higor wrote:The game automatically deallocates actors after you pile up at least 256 (i think) destroyed actors and this only happens between ticks, not in the middle of it.
The same code used into "Tick()" function, gave the same Accessed None's.