Search Unity

Bug Unity Transport issue with disconnects and new connections

Discussion in 'Entity Component System' started by jposey, Oct 8, 2020.

  1. jposey

    jposey

    Joined:
    Aug 14, 2014
    Posts:
    16
    I'm encountering issues in the Unity Transport package (0.4.1-preview.1) after having disconnects and new connections.

    I am able to reproduce it with the NetCube sample. I made a Win-Client build, ran the server in Unity Editor, and launched clients and closed them and opened new ones.

    With NetCube, if I limited it to only 1 client ever connected at a time, the problem was not reproducible. It seems to require having had a disconnect and then connecting a 2nd simultaneous client. In my own project, it is reproducible from 1 client connecting, disconnecting, and connecting again. The error and callstack are different from what happens in NetCube.

    Reproduction Steps using NetCube:
    1. Launch standalone NetCube server
    2. Launch first NetCube client
    3. Launch second NetCube client
    4. Close second NetCube client
    5. Launch third NetCube client

    Here is the error and callstack that gets spammed after this:

    ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
    Unity.Networking.Transport.DataStreamReader.ReadBytes (System.Byte* data, System.Int32 length) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/DataStream.cs:624)
    Unity.Networking.Transport.DataStreamReader.ReadULong () (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/DataStream.cs:682)
    Unity.NetCode.RpcSystem+RpcExecJob.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 chunkIndex, System.Int32 firstEntityIndex) (at Library/PackageCache/com.unity.netcode@0.4.0-preview.1/Runtime/Rpc/RpcSystem.cs:215)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].ExecuteInternal (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.14.0-preview.18/Unity.Entities/IJobChunk.cs:363)
    Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].Execute (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.14.0-preview.18/Unity.Entities/IJobChunk.cs:337)

    This is from my own project, and the error comes from the ReliableSequenced pipeline code.

    ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
    Unity.Networking.Transport.DataStreamReader.ReadBytes (System.Byte* data, System.Int32 length) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/DataStream.cs:624)
    Unity.Networking.Transport.ReliableSequencedPipelineStage.Receive (Unity.Networking.Transport.NetworkPipelineContext& ctx, Unity.Networking.Transport.InboundRecvBuffer& inboundBuffer, Unity.Networking.Transport.NetworkPipelineStage+Requests& requests) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/Pipelines/ReliableSequencedPipelineStage.cs:67)
    Unity.Networking.Transport.NetworkPipelineProcessor.ProcessReceiveStage (System.Int32 stage, Unity.Networking.Transport.NetworkPipeline pipeline, System.Int32 internalBufferOffset, System.Int32 internalSharedBufferOffset, Unity.Networking.Transport.NetworkPipelineContext& ctx, Unity.Networking.Transport.InboundRecvBuffer& inboundBuffer, Unity.Collections.NativeList`1[System.Int32]& resumeQ, System.Boolean& needsUpdate, System.Boolean& needsSendUpdate) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/NetworkPipeline.cs:912)
    Unity.Networking.Transport.NetworkPipelineProcessor.ProcessReceiveStagesFrom (Unity.Networking.Transport.NetworkDriver driver, System.Int32 startStage, Unity.Networking.Transport.NetworkPipeline pipeline, Unity.Networking.Transport.NetworkConnection connection, Unity.Networking.Transport.InboundRecvBuffer buffer) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/NetworkPipeline.cs:851)
    Unity.Networking.Transport.NetworkPipelineProcessor.Receive (Unity.Networking.Transport.NetworkDriver driver, Unity.Networking.Transport.NetworkConnection connection, Unity.Collections.NativeArray`1[T] buffer) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/NetworkPipeline.cs:819)
    Unity.Networking.Transport.NetworkDriver.AppendPacket (Unity.Networking.Transport.NetworkInterfaceEndPoint address, Unity.Networking.Transport.Protocols.UdpCHeader header, System.Int32 dataLen) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/NetworkDriver.cs:1328)
    Unity.Networking.Transport.NetworkPacketReceiver.AppendPacket (Unity.Networking.Transport.NetworkInterfaceEndPoint address, Unity.Networking.Transport.Protocols.UdpCHeader header, System.Int32 dataLen) (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/INetworkInterface.cs:25)
    Unity.Networking.Transport.BaselibNetworkInterface+ReceiveJob.Execute () (at Library/PackageCache/com.unity.transport@0.4.1-preview.1/Runtime/BaselibNetworkInterface.cs:326)
    Unity.Jobs.IJobExtensions+JobStruct`1[T].Execute (T& data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at <a9810827dce3444a8e5c4e9f3f5e0828>:0)
     
    Lukas_Kastern likes this.
  2. Kmsxkuse

    Kmsxkuse

    Joined:
    Feb 15, 2019
    Posts:
    306
    I've had the same problem but without errors.

    Completely new project, 2 files: Host and Client. Copy pasted straight from transport package Getting Started.

    Slight modification to client, a button that reconnects.

    First connection - disconnection works. Nothing out of the ordinary.

    Second connection - disconnection fails. Connection works but disconnection just doesnt seem to be recieved by Host. It's a LocalHost, there should be no network issues.

    Force reading from this orphaned connection on Host-side causes a whole bunch of errors. So the connection doesnt actually exist but no disconnection was sent.

    ScheduleUpdate() nor ScheduleFlushSend() seem to do anything Client or Host side. No difference adding or removing them.

    Restarting the client program while maintaining the host allows for reconnection. This makes me think it's something I'm not calling at disconnect to clear some sort of buffer causing memory leak in the client side. But the only method available is .Disconnect(driver) and I'm calling that. I even destroyed the driver a frame / Systembase cycle later to prevent race conditions with the driver being destroyed before disconnect is called.

    Internal memory leak? Am I just bad at copy pasting? Am I doing something wrong with my reconnect code, the rest of the code is copy pasted from Getting Started Jobify Client and Server code:

    Code (CSharp):
    1. protected override void OnCreate()
    2. {
    3.      RequireSingletonForUpdate<ClientActive>();
    4. }
    5.  
    6. protected override void OnStartRunning()
    7. {
    8.     Debug.LogError("Client Started!");
    9.  
    10.     if (_netDriver.IsCreated)
    11.         Debug.LogError("ERROR: Net driver already created.");
    12.  
    13.     _netDriver = NetworkDriver.Create();
    14.     _netDriver.CreatePipeline();
    15.  
    16.     var endPoint = NetworkEndPoint.Parse(TargetServerIP, 9568);
    17.     _connection = new NativeArray<NetworkConnection>(1, Allocator.Persistent)
    18.     {
    19.         [0] = _netDriver.Connect(endPoint)
    20.     };
    21.  
    22.     Debug.LogError($"Connection formed to {endPoint.Address}.");
    23. }
    24.  
    25. protected override void OnUpdate()
    26. {
    27.     Dependency = _netDriver.ScheduleUpdate(Dependency);
    28.     Dependency = _netDriver.ScheduleFlushSend(Dependency);
    29.    
    30.     var driver = _netDriver;
    31.     var connection = _connection;
    32.     Job
    33.         .WithCode(() =>
    34.         {
    35.             if (!connection[0].IsCreated)
    36.             {
    37.                 Debug.LogError("Client not connected.");
    38.                 return;
    39.             }
    40.  
    41.             NetworkEvent.Type cmd;
    42.             while ((cmd = connection[0].PopEvent(driver, out var stream)) != NetworkEvent.Type.Empty)
    43.             {
    44.                 switch (cmd)
    45.                 {
    46.                     case NetworkEvent.Type.Connect:
    47.                     {
    48.                         Debug.LogError("We are now connected to the server.");
    49.  
    50.                         uint value = 1;
    51.                         var writer = driver.BeginSend(connection[0]);
    52.                         writer.WriteUInt(value);
    53.                         driver.EndSend(writer);
    54.                         break;
    55.                     }
    56.                     case NetworkEvent.Type.Data:
    57.                     {
    58.                         uint value = stream.ReadUInt();
    59.                         Debug.LogError($"Got the value = {value} back from the server.");
    60.                         connection[0].Disconnect(driver);
    61.                         connection[0] = default;
    62.                         break;
    63.                     }
    64.                     case NetworkEvent.Type.Disconnect:
    65.                         Debug.LogError("Error: Client got disconnected from server.");
    66.                         connection[0] = default;
    67.                         break;
    68.                 }
    69.             }
    70.         }).Schedule();
    71.    
    72.     // Shutting down client loop.
    73.     if (_disconnected)
    74.         CompleteDependency();
    75.    
    76.     Entities
    77.         .WithAll<ClientActive>()
    78.         .ForEach((Entity entity) =>
    79.         {
    80.             if (connection[0].IsCreated)
    81.                 return;
    82.  
    83.             if (_disconnected)
    84.             {
    85.                 Debug.LogError("Entity destroyed.");
    86.                 EntityManager.DestroyEntity(entity);
    87.                 return;
    88.             }
    89.  
    90.             // Skipping a cycle for disconnection to properly work.
    91.             _disconnected = true;
    92.         }).WithStructuralChanges().WithoutBurst().Run();
    93.  
    94. protected override void OnStopRunning()
    95. {
    96.     CompleteDependency();
    97.  
    98.     _netDriver.Dispose();
    99.     _connection.Dispose();
    100. }
     
    Last edited: Oct 10, 2020
  3. Cuttlas-U

    Cuttlas-U

    Joined:
    Apr 11, 2017
    Posts:
    38
    any one was able to solve it ? still have this issue :(