Null exception

Discuss any questions about BEPUphysics or problems encountered.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Null exception

Post by tehDrop »

Hi, I'm getting this exception and just can't understand why it's happening. When I try to isolate it, it stops happening. All I know is that it seems to happen when I add or remove things from the space but not every time it only happens occasionally.

Code: Select all

System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=BEPUphysics
  StackTrace:
       at BEPUphysics.Constraints.Collision.ContactManifoldConstraint.UpdateSolverActivity()
       at BEPUphysics.Constraints.Solver.MultithreadedPrestep(Int32 i)
       at BEPUphysics.Threading.ParallelLoopWorker.Work()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
Also tried on a singlethreaded space but still happens. Any tips on what could be causing this exception?

Thanks.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

The difficulty in reproduction may imply threading issues. Are there any accesses to the engine from threads which aren't the thread which calls Space.Update, particularly adds/removes? If there are, they are the first suspects. It should be assumed that everything is not thread safe unless it's specifically noted to be thread safe.

Also, I would recommend updating to the latest version if you haven't already. I don't remember fixing any bugs like this, but eliminating the older versions' failures as potential causes is valuable.

If this isn't just some external thread corrupting state with asynchronous modification and it still happens in the newest version, then I'll likely need an isolated reproduction (preferably in the BEPUphysicsDemos) that I can fiddle with directly to figure it out.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

After a lot of attempts, I just can't reproduce it in isolation (it must be a very specific combination of factors I guess...)
Also, I'm sure nothing but the main thread (that calls Space.Update) is accessing the engine.

I know this is just an ugly hack and probably will break something later on or even lead to a memory leak (can't say since I don't know the engine internally) but this seems to fix the problem:

at BEPUphysics.Constraints.Collision.ContactManifoldConstraint.UpdateSolverActivity() added a null check:

isActiveInSolver = pair != null && pair.BroadPhaseOverlap.collisionRule < CollisionRule.NoSolver && (...)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

That particular fix may reduce the frequency of the failure, but it's probably going to show up again in a different way. If the pair is null in that function, the state of the manifold is corrupted.

Are immediate collision events being used? The collision events with present tense names execute within the engine update, so many actions which would be valid outside of the update or in a deferred event handler will blow everything up, with or without any threading involved. Adds and removes in an immediate event would be the most common way to break everything.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

I forgot to say but this Add/Remove that causes the exception should have to do with the character controller. Also I'm using the latest version of the main fork.

The only immediate collision event being used is in the CharacterController constructor:
Body.CollisionInformation.Events.DetectingInitialCollision += RemoveFriction;

Also the CharacterController (IBeforeSolverUpdateable) updates before the solver right? Could it be something the CharacterController is doing?

EDIT: it looks like it happens after removing the CharacterController from the space not adding it
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

Is this also with the latest CharacterController?
Also the CharacterController (IBeforeSolverUpdateable) updates before the solver right? Could it be something the CharacterController is doing?
I can't rule it out, but it's nearly impossible for me to narrow it down efficiently without a reproduction to work through.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

Yes, it's the latest one with no changed code except the CharacterControllerInput. As for the reproduction I'll keep trying.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

I'm still not able to replicate but I have a stress test in my game so the exception happens for sure after a couple of seconds. That's why I knew the fix I did before was "working".

So I reverted back to the unhacked physics library and tried to mess with the character controller settings to see if anything would stop the exception and when I set the maximum step height to 0, it doesn't happen anymore.

My guess is that there is a problem when a CharacterController is removed while performing stepping.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

Finally:

In the CharacterPlaygroundDemo, add this to the Update():

Code: Select all

if (base.Game.KeyboardInput.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.M))
                character.Deactivate();
            if (base.Game.KeyboardInput.IsKeyDown(Microsoft.Xna.Framework.Input.Keys.N))
                character.Activate();
Then as you're climbing the stairs, press M and N really quick (alternating)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

I've pinned down the cause, but it may take me a little while to puzzle out a proper solution to it. This is a low level, wide area of effect bug embedded in the complex and cheesy layers of a bookkeeping lasagna.

A couple of workarounds for this specific until the bug is actually fixed:
1) The pair null check in the constraint as you had should mostly work. It's not solid in the general case, but this particular path of failure should be blocked by the extra condition.

2) Remove everything but the Body.Position = newPosition line in the CharacterController.TeleportToPosition function. Without the pair.ClearContacts and pair.UpdateCollision in that function, the bug-required enqueued constraint adds won't exist.
Edit: The downside of doing this is potentially getting snagged on old contacts. It can feel a bit less smooth.

Note that similar failures could exist any time narrow phase-related constraint changes and Space.Removes occur near each other.
tehDrop
Posts: 20
Joined: Sat Dec 03, 2011 3:58 am

Re: Null exception

Post by tehDrop »

Alright, thanks Norbo! :D
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

It should be fixed now.

Apparently, 20 months ago, I tried to speed things up a little bit while introducing a subtle assumption about the order of stages. 2 months ago, I violated that assumption while fixing something else. Oops!

This is exactly the kind of bug that would sneak past many simpler tests and cause hard-to-reproduce failures out in the wild. Thanks for catching it! :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

I may have spoken too soon- my followup confirmation tests aren't working out so hot. I may have fixed one bug and reintroduced another, or perhaps these are separate unrelated bugs that have been hanging around.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

It appears to be a related but separate bug. Until it's properly fixed, a workaround is to insert a call to NarrowPhase.FlushGeneratedSolverUpdateables after the BeforeSolverUpdateables stage in Space.DoTimeStep like so:

Code: Select all

            void DoTimeStep()
        {
#if PROFILE
            start = Stopwatch.GetTimestamp();
#endif
            SpaceObjectBuffer.Update();
            EntityStateWriteBuffer.Update();
            DeactivationManager.Update();
            ForceUpdater.Update();
            DuringForcesUpdateables.Update();
            BoundingBoxUpdater.Update();
            BroadPhase.Update();
            BeforeNarrowPhaseUpdateables.Update();
            NarrowPhase.Update();
            BeforeSolverUpdateables.Update();
            NarrowPhase.FlushGeneratedSolverUpdateables();
            Solver.Update();
            BeforePositionUpdateUpdateables.Update();
            PositionUpdater.Update();
            BufferedStates.ReadBuffers.Update();
            DeferredEventDispatcher.Update();
            EndOfTimeStepUpdateables.Update();
#if PROFILE
            end = Stopwatch.GetTimestamp();
#endif


        }
This is still not quite solid, since any constraint adds/removes after the flush or before the solver update will cause the same problem. I'm working on picking out a more general solution.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Null exception

Post by Norbo »

Alright, all of it should be actually fixed now.
Post Reply