Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Server and client won't properly shutdown because of an ObjectDisposeException

Discussion in 'Unity Transport' started by Protvod, Aug 2, 2023.

  1. Protvod

    Protvod

    Joined:
    Feb 21, 2020
    Posts:
    8
    Whenever the server and client need to be shutdown, the following functions are called:
    Server:
    Variables:
    Code (CSharp):
    1.     public NetworkDriver driver;
    2.     private NativeList<NetworkConnection> connections;
    3.  
    4.     private bool isActive = false;
    Shutdown function:
    Code (CSharp):
    1. public void Shutdown()
    2.     {
    3.         if (isActive)
    4.         {
    5.             driver.Dispose();
    6.             connections.Dispose();
    7.             isActive = false;
    8.         }
    9.     }
    Client:
    Variables:
    Code (CSharp):
    1.     public NetworkDriver driver;
    2.     private NetworkConnection connection;
    3.  
    4.     private bool isActive = false;
    Shutdown function:
    Code (CSharp):
    1.     public void Shutdown()
    2.     {
    3.         if (isActive)
    4.         {
    5.             UnregisterToEvent();
    6.             driver.Dispose();
    7.             isActive = false;
    8.             connection = default(NetworkConnection);
    9.         }
    10.     }
    I followed this chess tutorial on youtube: https://www.youtube.com/playlist?list=PLmcbjnHce7SeAUFouc3X9zqXxiPbCz8Zp
    Everything I did was the same as what he did, except the fact that I used a newer version of com.unity.transport.

    The ObjectDisposeException I get is the following:
    1. ObjectDisposedException: The Unity.Collections.NativeList1[Unity.Networking.Transport.NetworkDriver+Connection] has been deallocated, it is not allowed to access it Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <e8a406da998549af9a2680936c7da25a>:0) Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <e8a406da998549af9a2680936c7da25a>:0) Unity.Collections.NativeList1[T].get_Length () (at Library/PackageCache/com.unity.collections@1.2.4/Unity.Collections/NativeList.cs:227) Unity.Networking.Transport.NetworkDriver.PopEventForConnection (Unity.Networking.Transport.NetworkConnection connectionId, Unity.Networking.Transport.DataStreamReader& reader, Unity.Networking.Transport.NetworkPipeline& pipeline) (at Library/PackageCache/com.unity.transport@1.4.0/Runtime/NetworkDriver.cs:1356) Unity.Networking.Transport.NetworkDriver.PopEventForConnection (Unity.Networking.Transport.NetworkConnection connectionId, Unity.Networking.Transport.DataStreamReader& reader) (at Library/PackageCache/com.unity.transport@1.4.0/Runtime/NetworkDriver.cs:1341) Unity.Networking.Transport.NetworkConnection.PopEvent (Unity.Networking.Transport.NetworkDriver driver, Unity.Networking.Transport.DataStreamReader& stream) (at Library/PackageCache/com.unity.transport@1.4.0/Runtime/NetworkConnection.cs:131) Client.UpdateMessagePump () (at Assets/Net/Client.cs:76) Client.Update () (at Assets/Net/Client.cs:61)
     
  2. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    416
    I haven't gone through the tutorial, but from the stack trace what is happening is that your
    Client.Update
    method is still calling
    PopEvent
    on a connection after the driver has been disposed of. Is it possible there's a missing check for
    isActive
    somewhere?
     
  3. Protvod

    Protvod

    Joined:
    Feb 21, 2020
    Posts:
    8
    There is a check for isActive in the Client.Update method
    Code (CSharp):
    1.     public void Update()
    2.     {
    3.         if (!isActive)
    4.             return;
    5.  
    6.         driver.ScheduleUpdate().Complete();
    7.         CheckAlive();
    8.  
    9.         UpdateMessagePump();
    10.     }
    The UpdateMessagePump() function is where the PopEvent is being called
    See below:
    Code (CSharp):
    1.     private void UpdateMessagePump()
    2.     {
    3.         DataStreamReader stream;
    4.         NetworkEvent.Type cmd;
    5.         while ((cmd = connection.PopEvent(driver, out stream)) != NetworkEvent.Type.Empty)
    6.         {
    7.  
    8.             if (cmd == NetworkEvent.Type.Connect)
    9.             {
    10.                 SendToServer(new NetWelcome());
    11.                 Debug.Log("We're connected, hurray!");
    12.             }
    13.             else if (cmd == NetworkEvent.Type.Data)
    14.             {
    15.                 NetUtility.OnData(stream, default(NetworkConnection));
    16.             }
    17.             else if (cmd == NetworkEvent.Type.Disconnect)
    18.             {
    19.                 Debug.Log("Client got disconnected from server");
    20.                 connection = default(NetworkConnection);
    21.                 connectionDropped?.Invoke();
    22.                 Shutdown();
    23.             }
    24.         }
    25.     }
     
  4. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    416
    When processing the
    Disconnect
    event and calling
    Shutdown
    , you're not exiting from the loop. Which means it will still call
    PopEvent
    on the next iteration, resulting in the object disposed exception. The call to
    Shutdown
    should be followed by a break statement.

    The same problem would occur if the
    NetUtility.OnData
    or
    CheckAlive
    methods were to call
    Shutdown
    . Perhaps it would be safer to include a check for
    isActive
    in that while loop where the events are processed:
    Code (CSharp):
    1. while (isActive && (cmd = ... )
     
  5. Protvod

    Protvod

    Joined:
    Feb 21, 2020
    Posts:
    8
    The error isn't given to me anymore, but I seem to still encounter the problems I encountered before. I thought these problems were related to the ObjectDisposeException. But I think I have clue on how to fix them.