0

Context: I'm using Unity to reach an endpoint, this endpoints belongs to me and is returning the correct type of information.

I'm starting my calls from here(with correct request):

public async Task<AuthenticationResponse> Login(AuthenticationRequest request)
    {
        AuthenticationResponse token = new AuthenticationResponse();
        await HttpClient.Post<AuthenticationResponse>(GetLoginEndPoint(), request);
        Debug.Log("000");
        //if (token.Success )
        //{
        //    this.refreshToken = token.RefreshToken;
        //    this.token = token.Token;
            
        //}
        return token;
    }

Post() from HttpClient gets called:

public static async Task<T> Post<T>(string endpoint, object payload)
    {
        var postRequest = CreateRequest(endpoint, RequestType.POST, payload);
        postRequest.SendWebRequest();

        while (!postRequest.isDone) { 
            await Task.Delay(20);
        }

        return JsonConvert.DeserializeObject<T>(postRequest.downloadHandler.text);
    }

Create Request:

   public static UnityWebRequest CreateRequest(string path, RequestType type = RequestType.GET, object data = null)
    {
        var request = new UnityWebRequest(path, type.ToString());


        if (data != null)
        {
            var bodyRaw = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
        }

        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json");

        return request;
    }

Currently it's doing nothing, but I've verified that it does return the correct AuthenticationResponse when code is not commented out.

After the method is called Unity SOMETIMES throws "A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details." and pauses the game

I've left the game run for 15 minutes before calling the Login() and no errors were thrown, after that I tried to login and then it throws the memory leak again.

I've enabled full StackTraces. After Login() is called and HttpClient.Post is done it Debug.Logs "000" as expected.

000
0x00007ff7d082041d (Unity) StackWalker::GetCurrentCallstack
0x00007ff7d0826fd9 (Unity) StackWalker::ShowCallstack
0x00007ff7d17c3973 (Unity) GetStacktrace
0x00007ff7d1e7419d (Unity) DebugStringToFile
0x00007ff7cf993372 (Unity) DebugLogHandler_CUSTOM_Internal_Log
0x000001e545734e8a (Mono JIT Code) (wrapper managed-to-native) UnityEngine.DebugLogHandler:Internal_Log (UnityEngine.LogType,UnityEngine.LogOption,string,UnityEngine.Object)
0x000001e545734cfb (Mono JIT Code) UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
0x000001e54573417e (Mono JIT Code) UnityEngine.Logger:Log (UnityEngine.LogType,object)
0x000001e545733e1d (Mono JIT Code) UnityEngine.Debug:Log (object)
0x000001e544fc3973 (Mono JIT Code) [DBConnectionManager.cs:71] DBConnectionManager/<Login>d__16:MoveNext () 
0x000001e545702aaa (Mono JIT Code) System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:InvokeMoveNext (object)
0x000001e5453497ee (Mono JIT Code) System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
0x000001e545348e2b (Mono JIT Code) System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
0x000001e54570273b (Mono JIT Code) System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:Run ()
0x000001e545733ac0 (Mono JIT Code) System.Threading.Tasks.AwaitTaskContinuation:InvokeAction (object)
0x000001e545700b94 (Mono JIT Code) System.Threading.Tasks.AwaitTaskContinuation:RunCallback (System.Threading.ContextCallback,object,System.Threading.Tasks.Task&)
0x000001e5457006bb (Mono JIT Code) System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation:Run (System.Threading.Tasks.Task,bool)
0x000001e5453a37b8 (Mono JIT Code) System.Threading.Tasks.Task:FinishContinuations ()
0x000001e5453a1d53 (Mono JIT Code) System.Threading.Tasks.Task:FinishStageThree ()
0x000001e5453b686b (Mono JIT Code) System.Threading.Tasks.Task`1<TResult_REF>:TrySetResult (TResult_REF)
0x000001e545733703 (Mono JIT Code) System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<TResult_REF>:SetResult (TResult_REF)
0x000001e544fc4b93 (Mono JIT Code) [HttpClient.cs:53] HttpClient/<Post>d__2`1<T_REF>:MoveNext () 
0x000001e545702aaa (Mono JIT Code) System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:InvokeMoveNext (object)
0x000001e5453497ee (Mono JIT Code) System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
0x000001e545348e2b (Mono JIT Code) System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool)
0x000001e54570273b (Mono JIT Code) System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:Run ()
0x000001e5457024d4 (Mono JIT Code) System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation/<>c:<.cctor>b__7_0 (object)
0x000001e54570229b (Mono JIT Code) UnityEngine.UnitySynchronizationContext/WorkRequest:Invoke ()
0x000001e544b1dfeb (Mono JIT Code) UnityEngine.UnitySynchronizationContext:Exec ()
0x000001e544b1db1b (Mono JIT Code) UnityEngine.UnitySynchronizationContext:ExecuteTasks ()
0x000001e544de1c45 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr)
0x00007ffb9e18fb04 (mono-2.0-bdwgc) [mini-runtime.c:3445] mono_jit_runtime_invoke 
0x00007ffb9e0ce7a4 (mono-2.0-bdwgc) [object.c:3066] do_runtime_invoke 
0x00007ffb9e0ce93c (mono-2.0-bdwgc) [object.c:3113] mono_runtime_invoke 
0x00007ff7d07433f4 (Unity) scripting_method_invoke
0x00007ff7d0722bf4 (Unity) ScriptingInvocation::Invoke
0x00007ff7d071d7f5 (Unity) ScriptingInvocation::Invoke<void>
0x00007ff7d086f1bb (Unity) Scripting::UnityEngine::UnitySynchronizationContextProxy::ExecuteTasks
0x00007ff7d0410926 (Unity) `InitPlayerLoopCallbacks'::`2'::UpdateScriptRunDelayedTasksRegistrator::Forward
0x00007ff7d03f69aa (Unity) ExecutePlayerLoop
0x00007ff7d03f6b36 (Unity) ExecutePlayerLoop
0x00007ff7d03fd0e9 (Unity) PlayerLoop
0x00007ff7d13765e9 (Unity) PlayerLoopController::UpdateScene
0x00007ff7d137478b (Unity) Application::TickTimer
0x00007ff7d17c9b0a (Unity) MainMessageLoop
0x00007ff7d17ce3db (Unity) WinMain
0x00007ff7d2bae77e (Unity) __scrt_common_main_seh
0x00007ffc70b27614 (KERNEL32) BaseThreadInitThunk
0x00007ffc717026b1 (ntdll) RtlUserThreadStart

I tried to make these methods barebone to confirm the source of the problem.

I need Unity to stop having memory leaks.

EDIT: I Found a reason! the Garbage collector was collecting postRequest while the task was waiting I patched the problem by adding a using:

 public static async Task<T> Post<T>(string endpoint, object payload)
    {
        using (var postRequest = CreateRequest(endpoint, RequestType.POST, payload)) { 

        postRequest.SendWebRequest();

        while (!postRequest.isDone) { 
            await Task.Delay(20);
        }

        return JsonConvert.DeserializeObject<T>(postRequest.downloadHandler.text);
        }
    }

I don't know if this is the appropriate way to fix this but it's working. Please inform me how else I should handle this problem.

Joao Silva
  • 23
  • 4
  • 2
    Start by disposing everything that is disposable (i.e. `*using* var request = new UnityWebRequest ...`. If the problems persist after you have done that, break out the memory debugger to see if you are leaking any objects. – JonasH Jul 20 '23 at 14:56
  • So I went to the memory debugger, when calling the method theres a spike in memory and then there's a spike in the GarbageCollector the memory goes back to its value before the memory spike and then the Memory leak error triggers, after unpausing there's no increase in memory compared to before, I can keep this loop going (error/unpause) and memory is not leaking anything... – Joao Silva Jul 20 '23 at 15:13
  • I have no specific knowledge about unity. But the error *might* mean "you forgot to dispose something, I fixed it for you, but you should *really* dispose the thing". I.e. an error message triggered by a finalizer being run. – JonasH Jul 21 '23 at 07:02

0 Answers0