Threading issues

Options
jaja1
jaja1
edited January 2015 in Photon Server
I recently updated my server code and began making use of tasks and the PoolFiber. While it solved some issues, a issue keeps coming up I just cant seem to solve. I know it is a threading issue I am just not sure how to deal with it. The issue comes up in my physics engine and I made a post on the forum to request help from the developer. While he did provide some insight into the problem he is still unable to help me debug my code remotely. Since my application's foundation is based on Photon's API I knew once the answer can't be found here I will have to delve in myself (and I have tried).
So here is the link to my post:
http://www.bepu-games.com/forum/viewtopic.php?f=4&t=2271&sid=954ff8723678aa7029b0adf942d188cc

The most updated and relevant code is the post before the last. It contains my issue in detail.

Really hoping to solve this ASAP. Thanks for all the replies in advance :)

EDIT:
The issue in full. For persons who may not prefer to see the full post or visit an external link.
Sorry to post on a slightly old thread, but the issue came up again and I just can't seem to narrow down the cause. Let me explain exactly what is going on.

The exception is a null reference exception. Here is my call stack and the exception:
CODE: SELECT ALL
2015-01-10 23:06:09,421 [17] DEBUG MukizuServer.CharacterGate [(null)] - System.NullReferenceException: Object reference not set to an instance of an object.
at BEPUphysics.BroadPhaseSystems.Hierarchies.InternalNode.TryToInsert(LeafNode node, Node& treeNode)
at BEPUphysics.BroadPhaseSystems.Hierarchies.DynamicHierarchy.Add(BroadPhaseEntry entry)
at BEPUphysics.Space.Add(ISpaceObject spaceObject)
at MukizuServer.PhysicsHandler.AddPlayerEntity() in c:\Users\jaja\Documents\Visual Studio 2010\Projects\MukizuServer\MukizuServer\PhysicsHandler.cs:line 128
2015-01-10 23:06:19,003 [21] DEBUG Photon.SocketServer.ApplicationBase [(null)] - OnDisconnect - ConnID=0
2015-01-10 23:06:19,034 [17] DEBUG MukizuServer.UnityClient [(null)] - 127.0.0.1 has disconnected.
2015-01-10 23:06:19,096 [13] DEBUG MukizuServer.SaveCharData [(null)] - System.NullReferenceException: Object reference not set to an instance of an object.
at MukizuServer.PhysicsHandler.RemovePlayer() in c:\Users\jaja\Documents\Visual Studio 2010\Projects\MukizuServer\MukizuServer\PhysicsHandler.cs:line 155


The AddPlayerEntity is called via a task within a Fiber pool. The same Fiber pool also schedules an update function that updates the Spaces I am adding entities too. Since both methods are called under ONE static "PoolFiber", I highly doubt entities are being added while the space is updating. This is the AddPlayerEntity method:

CODE: SELECT ALL
public void AddPlayerEntity()
{
try
{
float[] pos = playerPhysicsProfiler.init_pos;
float[] dir = playerPhysicsProfiler.init_dir;

Vector3 init_pos = new Vector3(pos[0], pos[1], pos[2]);

playerPhysicsProfiler.compactCollider = new Cylinder(init_pos, 1.5f, 0.2f);
playerPhysicsProfiler.extendedCollider = new Box(init_pos, 1.5f, 0.5f, 0.8f);
playerPhysicsProfiler.grabCollider = new Box(init_pos, 1f, 1f, 1f);

//offset local positions so that the colliders adhere to the "imaginary ground"
playerPhysicsProfiler.compactCollider.CollisionInformation.LocalPosition = new Vector3(0, 0.3f, 0.05f);
playerPhysicsProfiler.extendedCollider.CollisionInformation.LocalPosition = new Vector3(0, 0.4f, 0.7f);

//init orientation
playerPhysicsProfiler.extendedCollider.Orientation = new Quaternion(dir[0], dir[1], dir[2], dir[3]);

//set tags of colliders for recognition in collisions
playerPhysicsProfiler.compactCollider.Tag = "[PLAYER] [body] " + charStatsProfiler.char_name;
playerPhysicsProfiler.extendedCollider.Tag = "[PLAYER] [weapon] " + charStatsProfiler.char_name;
playerPhysicsProfiler.grabCollider.Tag = "[PLAYER] [grab] " + charStatsProfiler.char_name;

//enable collision on colliders
playerPhysicsProfiler.compactCollider.CollisionInformation.CollisionRules.Personal = BEPUphysics.CollisionRuleManagement.CollisionRule.Normal;
playerPhysicsProfiler.extendedCollider.CollisionInformation.CollisionRules.Personal = BEPUphysics.CollisionRuleManagement.CollisionRule.Normal;
playerPhysicsProfiler.grabCollider.CollisionInformation.CollisionRules.Personal = BEPUphysics.CollisionRuleManagement.CollisionRule.Normal;

//initialize movers/rotators
playerPhysicsProfiler.charCompactMover = new EntityMover(playerPhysicsProfiler.compactCollider);
playerPhysicsProfiler.charExtendedMover = new EntityMover(playerPhysicsProfiler.extendedCollider);
playerPhysicsProfiler.charGrabMover = new EntityMover(playerPhysicsProfiler.grabCollider);
playerPhysicsProfiler.charExtendedRotator = new EntityRotator(playerPhysicsProfiler.extendedCollider);

#region map stuff

if (playerPhysicsProfiler.currentMap == 0.00f)//vandellia
{
VandelliaPhysicsMap.Add(playerPhysicsProfiler.compactCollider);
VandelliaPhysicsMap.Add(playerPhysicsProfiler.extendedCollider);//THIS IS LINE 128
VandelliaPhysicsMap.Add(playerPhysicsProfiler.grabCollider);
VandelliaPhysicsMap.Add(playerPhysicsProfiler.charCompactMover);
VandelliaPhysicsMap.Add(playerPhysicsProfiler.charExtendedMover);
VandelliaPhysicsMap.Add(playerPhysicsProfiler.charGrabMover);
VandelliaPhysicsMap.Add(playerPhysicsProfiler.charExtendedRotator);
}
else return;

#endregion

isPlayerAdded = true;
return;
}
catch (Exception e)
{
Log.Debug(e);
return;
}
}


I commented in the location of line 128.
Also, here is where I implement the task to call this method.
CODE: SELECT ALL
PhysicsHandler p = new PhysicsHandler();
p.uClient = uClient;
p.charStatsProfiler = charProfiler;
p.playerPhysicsProfiler = physProfiler;
Task t = new Task(p.AddPlayerEntity);
PhysicsHandler.PhysicsFiber.Enqueue(t.Start);
t.Wait();

I created a new instance of the physics handler class to call the method and avoid race conditions (apparently did not work). However, I state againt the fiber pool is static.

The second exception is called on this method:

CODE: SELECT ALL
public void RemovePlayer()
{
PlayerPhysicsProfiler pprof = uClient._playerPhysicsProfiler;
try
{
pprof.charCompactMover.Space.Remove(pprof.charCompactMover);//THIS IS LINE 155
pprof.charExtendedMover.Space.Remove(pprof.charExtendedMover);
pprof.charGrabMover.Space.Remove(pprof.charGrabMover);
pprof.charExtendedRotator.Space.Remove(pprof.charExtendedRotator);
pprof.compactCollider.Space.Remove(pprof.compactCollider);
pprof.extendedCollider.Space.Remove(pprof.extendedCollider);
pprof.grabCollider.Space.Remove(pprof.grabCollider);
pprof = new PlayerPhysicsProfiler();

if (SaveCharData.isWaitingToSwitchChar)
{
OperationResponse response = new OperationResponse((byte)15);
response.Parameters = new Dictionary<byte, object> { { 15, null } };
SendParameters sendParameters = new SendParameters();
sendParameters.Unreliable = true;
uClient.SendOperationResponse(response, sendParameters);
}

return;
}
catch (Exception e)
{
Log.Debug(e);
return;
}
}


Once again I commented in the location of line 155.
Here is where I queued the method: (I did not use Task.Wait() in this case because I had no code to call after the method had completed. In retrospect I'm thinking it was still necessary? :? )
CODE: SELECT ALL
PhysicsHandler p = new PhysicsHandler();
p.uClient = uClient;
PhysicsHandler.PhysicsFiber.Enqueue(p.RemovePlayer);


It is one of those "random" errors so I guess its another race condition. But what is the exact cause of this one is what I can't seem to find. The strange thing about it too is that the exception is always called on these exact same lines. The exception may happen randomly (and too frequent a case to simply ignore), but the same lines always bug out.

I also have another "random" issue on a monster entity when it dies and respawns. I can't provide an debug log because there is no error...client side nor server side. So for now I will assume it is a logical error and if the previous issue is solved I will try to tackle this one with new knowledge.
EDIT: It was a logical error so the monster issue is fixed....the problem mentioned above about the player however still persists. I did try locks.

So, is there any further advice you can give me on this problem Norbo?

Comments

  • chvetsov
    Options
    Hi, jaja1

    This code is totaly buggy and useless.
    >>Task t = new Task(p.AddPlayerEntity);
    >>PhysicsHandler.PhysicsFiber.Enqueue(t.Start);
    >>t.Wait();
    it ONLY STARTS task in fiber. after task is started, fiber will execute next task. and this next task will be executed paralelly with just started task.
    we gave you many other ideas how to implement this part. Please find different way to implement this part