ChainSafe / web3.unity

🕹 Unity SDK for building games that interact with blockchains.
GNU Lesser General Public License v3.0
922 stars 236 forks source link

CSWebsocket `ObjectDisposedException: Cannot access a disposed object.` #1215

Open TheOneVries opened 1 week ago

TheOneVries commented 1 week ago

When connecting to wallet using the 'remember me' functionality, using admittedly not the most reliable internet connection, I regularly find unity crash when calling public async Task Close() on CSWebSocket.cs

This is a connection made via WalletConnect, connecting to MetaMask. Mostly this works fine, but occasionally this error occurs, leading me to believe the issue lies with internet connection.

I am afraid I cannot provide a sample project or anything.

Console errors

ObjectDisposedException: Cannot access a disposed object. Object name: 'MobileAuthenticatedStream'. Mono.Net.Security.MobileAuthenticatedStream.StartOperation (Mono.Net.Security.MobileAuthenticatedStream+OperationType type, Mono.Net.Security.AsyncProtocolRequest asyncRequest, System.Threading.CancellationToken cancellationToken) (at <09cbc7ca916345fdbceb45137018efd3>:0) System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync (System.Int32 minimumRequiredBytes, System.Threading.CancellationToken cancellationToken, System.Boolean throwOnPrematureClosure) (at <09cbc7ca916345fdbceb45137018efd3>:0) System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult] (System.Memory1[T] payloadBuffer, System.Threading.CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter) (at <09cbc7ca916345fdbceb45137018efd3>:0) Rethrow as OperationCanceledException: Aborted System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult] (System.Memory1[T] payloadBuffer, System.Threading.CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter) (at <09cbc7ca916345fdbceb45137018efd3>:0) System.Net.WebSockets.ManagedWebSocket.CloseAsyncPrivate (System.Net.WebSockets.WebSocketCloseStatus closeStatus, System.String statusDescription, System.Threading.CancellationToken cancellationToken) (at <09cbc7ca916345fdbceb45137018efd3>:0) NativeWebSocket.WebSocket.Close () (at ./Library/PackageCache/io.chainsafe.web3-unity@f92323a1ea/Runtime/Plugins/WebSocket/CSWebSocket.cs:709) ChainSafe.Gaming.WalletConnect.WebSocketConnection.Dispose () (at ./Library/PackageCache/io.chainsafe.web3-unity@f92323a1ea/Runtime/Scripts/WalletConnect/WebSocketConnection.cs:279) System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__7_0 (System.Object state) (at <31687ccd371e4dc6b0c23a1317cf9474>:0) UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () (at <50e5acd061cd4a73b7fc8eecbf07e915>:0) UnityEngine.UnitySynchronizationContext.Exec () (at <50e5acd061cd4a73b7fc8eecbf07e915>:0) UnityEngine.UnitySynchronizationContext.ExecuteTasks () (at <50e5acd061cd4a73b7fc8eecbf07e915>:0)

Desktop (please complete the following information):

kantagara commented 3 days ago

Question: are you using ABI to C# contract generator?

TheOneVries commented 3 days ago

Yes I do, but this is not happening via contract calls; this happens on initial wallet connect. Sorry I should have clarified further. So in my connect script I call await Web3Unity.Instance.Initialize(rememberMe); Somewhere during this process it seems public async Task Close() appears to be called in CSWebSocket.cs (in the WebSocket class), which is where this error can occur...

I should mention that this happens in the editor, and I've also noticed that this never happens on first play, so this might have to do with objects not properly being disposed of when stopping a game and starting again? Either way, I've put the code in Task Close() in a try-catch like so:

public async Task Close()
{
    if (State == WebSocketState.Open)
    {
        try
        {
            await m_Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, m_CancellationToken);
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogWarning(">> WebSocket exception: " + e.Message);
        }
    }
}

And this seems to work fine... even when I try to connect and it catches an exception (which typically has the message 'Aborted'), the connection still ends up being successful. So yeah; I suspect this error is actually caused by the Close() being called via objects still lingering from a previous session, except the object they're calling it on no longer exists? Something like that? Either way, I think for editor purposes a try/catch solves it. For me it does :D

kantagara commented 3 days ago

If you want , you can add that fix to our repo and help us out in true open-source manner. We would be more than happy to accept your PR!