User Reporting SDK: A Native Collection has not been disposed, resulting in a memory leak

Hi,

I’m using Unity 2021.2.11f and I’ve just enabled Cloud Diagnostics and added the User Reporting SDK.
Haven’t changed a thing but when I start or stop play mode, this error occurs:

These are the 340-341 lines of UserReportingScript

string url = string.Format("https://userreporting.cloud.unity3d.com/api/userreporting/projects/{0}/ping", UnityUserReporting.CurrentClient.ProjectIdentifier);
UnityUserReporting.CurrentClient.Platform.Post(url, "application/json", Encoding.UTF8.GetBytes("\"Ping\""), (upload, download) => { }, (result, bytes) => { });

These are 376-377 lines of UnityUserReportingPlatform:

UnityWebRequest webRequest = new UnityWebRequest(endpoint, "POST");
webRequest.uploadHandler = new UploadHandlerRaw(content);

Did I configured something badly? Or is this an issue with the package?

Thanks in advance!

1 Like

The sdk will be released as a package manager package somewhere soon where this is fixed. We either stay with the old one or wait for the new one to be released.

1 Like

Hello, any ETA about how ‘soon’ can we expect the package to appear ?
Isn’t it problematic that the current one to download is flawed with that memory leak ? How to revert to the ‘old one’ ?
Thanks :slight_smile:

No update for a while: Where to get the SDK?

Edit: There is currently only the flawed one, the new is not yet released and maybe, who knows, it may never will. Maybe Unity wants us to pay for an advanced version and bury the old one.

What a disgrace -_-. Thanks for the info!

1 Like

Insert these two lines in UnityUserReportingPlatform line 379 and I believe it fixes this error.

webRequest.disposeUploadHandlerOnDispose = true;
webRequest.disposeDownloadHandlerOnDispose = true;

Not sure why they don’t have this on package manager yet, or why they haven’t at least fixed the downloadable one.

^ Disposing on line 379 doesn’t work. Since webrequest is cached in postOperation and later f’s.
Instead try this:
Where you are initializing IUserReportingPlatform

Assembly assembly = Assembly.GetExecutingAssembly();
Type asyncUnityUserReportingPlatformType =
assembly.GetType("Unity.Cloud.UserReporting.Plugin.Version2018_3.AsyncUnityUserReportingPlatform");
if (asyncUnityUserReportingPlatformType != null)
{
object activatedObject = Activator.CreateInstance(asyncUnityUserReportingPlatformType);
IUserReportingPlatform asyncUnityUserReportingPlatform = activatedObject as IUserReportingPlatform;
if (asyncUnityUserReportingPlatform != null)
{
UnityUserReporting.Configure(asyncUnityUserReportingPlatform, this.GetConfiguration());
configured = true;
}
}

You can see you create an instance of this. Therefore you can also dispose of this. What I’ve done is to extend interface

public interface IUserReportingPlatform :IDisposable

It will give you error of those instances. In the dispose methods just set all the class fields to null.
For example:
In “UnityUserReportingPlatform.cs”

public void Dispose()
{
this.postOperations = null;
this.logMessages = null;
this.profilerSamplers = null;
this.screenshotOperations = null;
this.screenshotStopwatch = null;
this.taskOperations = null;
}

And call the cached Dispose()

Hello, just to be clear, calling the dispose() is required at UnityUserReportingPlatform line 379, is that right ?
In any case, thanks a lot for helping, you’re very kind !
I can’t believe Unity team didn’t yet backported a fix for such a huge leak in an active LTS like 2021.3 X/.

I also seem to have to add a dispose method there (empty that is) in that script, it’s legit right ?
8905905--1219026--upload_2023-3-27_12-19-4.png
as well as here:
8905905--1219029--upload_2023-3-27_12-21-20.png

It doesn’t really matter if there is an empty method. Since it is required be implementing this interface now with dispose it needs to have it.

After that you need to call the DIspose() from somewhere (probably from the place you started creating IUserReportingPlatform) when you don’t need it anymore i.e. OnApplicationQuit()

1 Like

What I did to fix was I modified my Post() method in UnityUserReportingPlatform to be…

        public void Post(string endpoint, string contentType, byte[] content, Action<float, float> progressCallback, Action<bool, byte[]> callback)
        {
            UnityWebRequest webRequest = new UnityWebRequest(endpoint, "POST");
            webRequest.uploadHandler = new UploadHandlerRaw(content);
            webRequest.downloadHandler = new DownloadHandlerBuffer();
            webRequest.disposeCertificateHandlerOnDispose = true;
            webRequest.disposeDownloadHandlerOnDispose = true;
            webRequest.disposeUploadHandlerOnDispose = true;
            webRequest.SetRequestHeader("Content-Type", contentType);
            webRequest.SendWebRequest();
            UnityUserReportingPlatform.PostOperation postOperation = new UnityUserReportingPlatform.PostOperation();
            postOperation.WebRequest = webRequest;
            postOperation.Callback = callback;
            postOperation.ProgressCallback = progressCallback;
            this.postOperations.Add(postOperation);
            
            UnityUserReportingPlatform.PostOperation postOperation2 = new UnityUserReportingPlatform.PostOperation();
            postOperation2.WebRequest = webRequest;
            postOperation2.Callback = new Action<bool, byte[]>((bool success, byte[] data) => {
                webRequest.Dispose();
            });
            postOperation2.ProgressCallback = progressCallback;
            this.postOperations.Add(postOperation2);
        }

This should ensure that the original web request gets disposed after all callbacks have completed.
Fix your crap Unity.

Unity released a package version of it a while ago that fixed all these issues. See here: About User Reporting