Code concurrence problem with Timer and None check

Discussions about Coding and Scripting
Post Reply
User avatar
PrinceOfFunky
Godlike
Posts: 1200
Joined: Mon Aug 31, 2015 10:31 pm

Code concurrence problem with Timer and None check

Post 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?
"Your stuff is known to be buggy and unfinished/not properly tested"
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Code concurrence problem with Timer and None check

Post 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.
User avatar
Barbie
Godlike
Posts: 2792
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Code concurrence problem with Timer and None check

Post 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.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Code concurrence problem with Timer and None check

Post 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).
Last edited by sektor2111 on Wed Sep 28, 2016 6:17 am, edited 3 times in total.
User avatar
PrinceOfFunky
Godlike
Posts: 1200
Joined: Mon Aug 31, 2015 10:31 pm

Re: Code concurrence problem with Timer and None check

Post 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?)
"Your stuff is known to be buggy and unfinished/not properly tested"
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: Code concurrence problem with Timer and None check

Post 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.
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Code concurrence problem with Timer and None check

Post 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.
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: Code concurrence problem with Timer and None check

Post 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.
User avatar
PrinceOfFunky
Godlike
Posts: 1200
Joined: Mon Aug 31, 2015 10:31 pm

Re: Code concurrence problem with Timer and None check

Post 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.
"Your stuff is known to be buggy and unfinished/not properly tested"
Post Reply