Search Unity

[Transport] NetworkDriver.Concurrent.PopEventForConnection NullReferenceException

Discussion in 'Unity Transport' started by hugeandy, May 27, 2021.

  1. hugeandy

    hugeandy

    Joined:
    Nov 2, 2016
    Posts:
    131
    Hi all,

    I'm getting the following exception from our implementation of the transport package. The exception only happens in build. In editor there are no errors. The exception only happens when a connection is made to the server. I have tried both scheduling the job and running it as seen from commented out code. When I schedule the job, the player crashes, when I run it I get the exception

    Find the source for ServerUpdateJob and where I schedule/run it below

    Transport 0.8.0-preview.8
    Jobs 0.8.0-preview.23
    Burst 1.5.3

    Any tips on how I can debug this further would be greatly appreciated.

    Cheers,
    Andy

    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2.   at Unity.Collections.NativeList`1[T].get_Length () [0x00001] in C:\BuildAgent\work\fb1ca7e713fe6fa1\Library\PackageCache\com.unity.collections@0.17.0-preview.18\Unity.Collections\NativeList.cs:225
    3.   at Unity.Networking.Transport.NetworkDriver+Concurrent.PopEventForConnection (Unity.Networking.Transport.NetworkConnection connectionId, Unity.Networking.Transport.DataStreamReader& reader, Unity.Networking.Transport.NetworkPipeline& pipeline) [0x0000f] in C:\BuildAgent\work\fb1ca7e713fe6fa1\Library\PackageCache\com.unity.transport@0.8.0-preview.8\Runtime\NetworkDriver.cs:90
    4.   at Unity.Networking.Transport.NetworkDriver+Concurrent.PopEventForConnection (Unity.Networking.Transport.NetworkConnection connectionId, Unity.Networking.Transport.DataStreamReader& reader) [0x00001] in C:\BuildAgent\work\fb1ca7e713fe6fa1\Library\PackageCache\com.unity.transport@0.8.0-preview.8\Runtime\NetworkDriver.cs:81
    5.   at hugecalf.netcode.ServerUpdateJob.Execute () [0x00025] in C:\BuildAgent\work\fb1ca7e713fe6fa1\Packages\com.hugecalf.netcode\Runtime\ServerUpdateJob.cs:30
    6.   at Unity.Jobs.IJobExtensions+JobStruct`1[T].Execute (T& data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) [0x00001] in <19684f84c6314f4e90bb9f0493eb99b2>:0
    7.   at (wrapper delegate-invoke) Unity.Jobs.IJobExtensions+JobStruct`1+ExecuteJobFunction[hugecalf.netcode.ServerUpdateJob].invoke_void_T&_intptr_intptr_JobRanges&_int(hugecalf.netcode.ServerUpdateJob&,intptr,intptr,Unity.Jobs.LowLevel.Unsafe.JobRanges&,int)
    8. Unity.Jobs.LowLevel.Unsafe.JobsUtility:Schedule_Injected(JobScheduleParameters&, JobHandle&)
    9. Unity.Jobs.LowLevel.Unsafe.JobsUtility:Schedule(JobScheduleParameters&)
    10. Unity.Jobs.IJobExtensions:Run(ServerUpdateJob)
    11. hugecalf.netcode.ServerNetPacketHandler:Process() (at C:\BuildAgent\work\fb1ca7e713fe6fa1\Packages\com.hugecalf.netcode\Runtime\Server.cs:129)
    12. hugecalf.netcode.NetPacketHandler:Update() (at C:\BuildAgent\work\fb1ca7e713fe6fa1\Packages\com.hugecalf.netcode\Runtime\JobifiedNetPacketHandler.cs:84)
    13. net.server.GameServer:Update() (at C:\BuildAgent\work\fb1ca7e713fe6fa1\Assets\Scripts\net\server\GameServer.cs:138)
    14.  
    Code (CSharp):
    1. [BurstCompile]
    2. public struct ServerUpdateJob : IJob {
    3.     public NetworkDriver.Concurrent Driver;
    4.     public NativeArray<NetworkConnection> Connections;
    5.  
    6.     public void Execute() {
    7.         for (var i = 0; i < Connections.Length; i++) {
    8.             var connection = Connections[i];
    9.             Assert.IsTrue(connection.IsCreated);
    10.  
    11.             NetworkEvent.Type command;
    12.             while ((command = Driver.PopEventForConnection(connection, out var reader)) != NetworkEvent.Type.Empty) {
    13.                 if (command == NetworkEvent.Type.Data) {
    14.                     //on data
    15.                 }
    16.                 else if (command == NetworkEvent.Type.Disconnect) {
    17.                     Connections[i] = default;
    18.                 }
    19.             }
    20.         }
    21.     }
    22. }
    Code (CSharp):
    1. jobHandle.Complete();
    2.  
    3. var connectionJob = new ServerConnectionsUpdateJob {
    4.     Driver = driver,
    5.     Connections = connections,
    6.     NewConnections = newConnections
    7. };
    8.          
    9. var updateJob = new ServerUpdateJob {
    10.     Driver = concurrentDriver,
    11.     Connections = connections.AsDeferredJobArray(),
    12. };
    13.  
    14. jobHandle = driver.ScheduleUpdate(jobHandle);
    15. jobHandle = connectionJob.Schedule(jobHandle);
    16.          
    17. // jobHandle = updateJob.Schedule(jobHandle);
    18. jobHandle.Complete();
    19. updateJob.Run();
    20. jobHandle = ScheduleDeserialise(jobHandle);

    Code (CSharp):
    1. connections = new NativeList<NetworkConnection>(MaxConnections, Allocator.Persistent);
     
    Last edited: May 27, 2021
  2. timjohansson

    timjohansson

    Unity Technologies

    Joined:
    Jul 13, 2016
    Posts:
    473
    Moving this to the transport forums.

    The use of `connections.AsDeferredJobArray()` looks very strange to me. AsDeferredJobArray is for use with IJobParallelForDefer - and you are not using that.

    The error looks more like concurrentDriver is not setup correctly though, it looks like the crash is on the first access to internal state in concurrentDriver.
    Some calls to the driver will invalidate the concurrent driver so you have to call.ToConcurrent again - I think bind is one of them.
     
  3. hugeandy

    hugeandy

    Joined:
    Nov 2, 2016
    Posts:
    131
    Thanks @timjohansson, I didn't know there was a dedicated transport forum - will post here in future

    THIS sounds likely, as I made the very "wise" move to cache the call to ToConcurrent after creating the driver. I will reevaluate it every time it is needed, make a build and test

    I will also look into that AsDeferredJobArray() call, as I have adapted my code from the example which does use IJobParallelForDefer. Thinking about it though, doesn't the conversion to the NativeArray does still need to be deferred until the job actually runs? Maybe I misunderstand.

    Cheers!
     
  4. hugeandy

    hugeandy

    Joined:
    Nov 2, 2016
    Posts:
    131
    Yep that has done the trick, thanks a lot!