Obi Official Forum

Full Version: [FIXED] Dispose of atomic safety handle error when game start
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Code:
System.ObjectDisposedException: The UNKNOWN_OBJECT_TYPE has been deallocated, it is not allowed to access it
  at (wrapper managed-to-native) Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow_Injected(Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle&)
  at Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) [0x00000] in <b41119cc6741409ea29f63c7f98de938>:0
  at Obi.ObiNativeList`1[T].Dispose (System.Boolean disposing) [0x0003f] in ....\Standard Assets\Vendor\Obi\Scripts\Common\DataStructures\NativeList\ObiNativeList.cs
[attachment=1952]

Hi, I got an error message after game start while using the Obi , as shown above.

Please help me to fix this error

The following is the current version information used in the project
Unity 2022.3.6f1
Burst 1.8.8
Jobs 0.70.0-preview(Exp)
URP 14.0.8
Mathematics 1.2.6
Collections 2.1.4

Obi Cloth 6.5.4
Obi Rope 6.5.4
[attachment=1951]
If you need further information, please let me know

12月1日 1:02


[attachment=1953]


I checked the error code and found strange parts. 
The Dispose process used Bool, but it was not actually used in the Function
Therefore, I added a correction, but I am not sure if this correction is correct. 

After more digging . I think Obi's implementation of Create and Dispose may have missed implementations, resulting in Dispose not running properly.
If anyone is also investigating, welcome to join
(01-12-2023, 03:22 AM)kaser Wrote: [ -> ]
Code:
System.ObjectDisposedException: The UNKNOWN_OBJECT_TYPE has been deallocated, it is not allowed to access it
  at (wrapper managed-to-native) Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow_Injected(Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle&)
  at Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckDeallocateAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) [0x00000] in <b41119cc6741409ea29f63c7f98de938>:0
  at Obi.ObiNativeList`1[T].Dispose (System.Boolean disposing) [0x0003f] in ....\Standard Assets\Vendor\Obi\Scripts\Common\DataStructures\NativeList\ObiNativeList.cs
[color=#1a1a1a][size=small][font=-apple-system, BlinkMacSystemFont,][color=#242424][size=small][font=-apple-system, BlinkMacSystemFont,]

Hi, I got an error message after game start while using the Obi , as shown above.


Hi,

I'm unable to reproduce this. Could you describe under what situations does this happen?

(01-12-2023, 03:22 AM)kaser Wrote: [ -> ]Please help me to fix this error

This error is raised by Unity's job safety system. If it only happens in the editor, disabling the safety checks in the Jobs menu should get rid of it. This is of course not ideal, but shouldn't affect runtime behavior.

(01-12-2023, 03:22 AM)kaser Wrote: [ -> ]I checked the error code and found strange parts. 
The Dispose process used Bool, but it was not actually used in the Function
Therefore, I added a correction, but I am not sure if this correction is correct. 
After more digging . I think Obi's implementation of Create and Dispose may have missed implementations, resulting in Dispose not running properly.
If anyone is also investigating, welcome to join

https://learn.microsoft.com/en-us/dotnet...ng-dispose

The boolean parameter in Dispose(bool) lets you know whether the method is called by a finalizer (similar to a destructor in C/C++) or by manually calling the Dispose() method. In both cases we need to release the safety handle, so the correct thing in this case is to ignore the parameter.
(01-12-2023, 06:36 AM)josemendez Wrote: [ -> ]Hi,

I'm unable to reproduce this. Could you describe under what situations does this happen?


This error is raised by Unity's job safety system. If it only happens in the editor, disabling the safety checks in the Jobs menu should get rid of it. This is of course not ideal, but shouldn't affect runtime behavior.


https://learn.microsoft.com/en-us/dotnet...ng-dispose

The boolean parameter in Dispose(bool) lets you know whether the method is called by a finalizer (similar to a destructor in C/C++) or by manually calling the Dispose() method. In both cases we need to release the safety handle, so the correct thing in this case is to ignore the parameter.


I have already passed on the testing project to you. Could you please confirm again
(01-12-2023, 07:25 AM)kaser Wrote: [ -> ]I have already passed on the testing project to you. Could you please confirm again

Got the project, will check it out now.
I'm unable to reproduce the issue on Unity 2022.3, however I could reproduce it in 2023.1. Seems like the ObiNativeList constructor is not being called by Unity when deserializing it in the editor, but the safety handle is destroyed in Dispose() regardless.

Move the atomic safety handle release inside the if (isCreated){} conditional, like so:

Code:
protected void Dispose(bool disposing)
        {
            if (isCreated)
            {

                // dispose of compuse buffer representation:
                if (m_ComputeBuffer != null)
                {
                    m_ComputeBuffer.Dispose();
                }

                // free unmanaged memory buffer:
                UnsafeUtility.Free(m_AlignedPtr, Allocator.Persistent);
                m_AlignedPtr = null;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                try
                {
                    // dispose of atomic safety handle:
                    AtomicSafetyHandle.CheckDeallocateAndThrow(m_SafetyHandle);
                    AtomicSafetyHandle.Release(m_SafetyHandle);
                }
                catch (Exception ex)
                {
                    Debug.LogError(ex);
                }
#endif
            }

        }

This ensures that the safety handle is only attempted to be destroyed if the array has had its constructor called and m_AlignedPtr is not null.

let me know how it goes,

kind regards
Hello, I have tried the solution the error was disappear but...
This approach may cause memory leak issues.

When False, the possible cause of memory leak is that the AtomicSafetyHandle.Release was not executed correctly
(01-12-2023, 07:50 AM)kaser Wrote: [ -> ]Hello, I have tried the solution the error was disappear but...
This approach may cause memory leak issues.

When False, the possible cause of memory leak is that the AtomicSafetyHandle.Release was not executed correctly

As long as the list's constructor is called, isCreated will be true and the safety handle will exist.

Only in cases where the constructor hasn't been called or Dispose() has been already called, isCreated will be false. This prevents double deallocations of the safety handle and attempting to deallocate it when it doesn't exist.

Typically, Obi's own code always calls the constructor of the list, so even with the original code there are no cases where a null safety handle is destroyed if the list has been properly created. However, seems like newer Unity versions can create an instance of the list during serialization without calling its constructor, but will call Dispose() when destroying it nonetheless. Making sure that the safety handle is only destroyed if the list has had its constructor called is the correct thing to do.

Also note that safety handles are only ever used when the editor's safety system is enabled, and are skipped entirely in builds.

kind regards,
Thanks response.

[attachment=1954]

There is a section I would like to add regarding the issue of memory leak that was just mentioned

In the base Class of the original abstract type, there are two Constructors.



The object inheriting this Class is being implemented, and it seems that not two implementation types are being used.

Therefore, when using isCreated as a judgment, such as the Int type List in the image below, there may be memory leaks due to incorrect constructor and not call ChangeCapacity at all, resulting in isCreated not being judged as true.
[attachment=1955]

By the way here is a simple way to check memory is leak or not
[attachment=1956]

The above is my current interpretation. If there are any inaccuracies, please let me know


Is it possible for the above issues to exist in the Obi system Flow?
(01-12-2023, 08:38 AM)kaser Wrote: [ -> ]Thanks response.



There is a section I would like to add regarding the issue of memory leak that was just mentioned

In the base Class of the original abstract type, there are two materialized implementations.

The object inheriting this Class is being implemented, and it seems that not two implementation types are being used.

Some concrete implementations of ObiNativeList<T> override/hide the parameterless constructor, as it's not supposed to do anything even when called by Unity. These are lists of data types that get serialized as part of assets (mainly, actor blueprints).

(01-12-2023, 08:38 AM)kaser Wrote: [ -> ]Therefore, when using isCreated as a judgment, such as the Int type List in the image below, there may be memory leaks due to incorrect implementation of ChangeCapacity, resulting in isCreated not being judged as true.The above is my current interpretation. If there are any inaccuracies, please let me know
Is it possible for the above issues to exist in the Obi system Flow?

I'm not sure I understand your explanation, ChangeCapacity is not only called by the list's constructor. It is also called when adding individual elements or a range of elements to the list, basically in any situation that we need to actually store something in the list.

As a result, even if the constructor is not called isCreated will be set true as soon as the list is used for the first time. As far as I can tell, there's no situation in which isCreated can be be false and the safety handle be valid simultaneously, leading to a leak (as a side note, AtomicSafetyHandle is a struct so it can't be leaked. They only exist to perform checks on other object's lifetimes).

However if the constructor is not called (and the safety handle is hence invalid) and the list is never used (so no ChangeCapacity calls either) and Dispose is called, it will attempt to destroy a handle that doesn't exist.

While this may seem reasonable from a user's perspective (raising an exception when attempting to destroy a list that hasn't had all of its data initialized), Unity's serialization system uses the list in this way. Making the safety handle destruction code depend on isCreated is correct as it will only attempt to destroy the safety handle if the list is properly initialized, as opposed to trying and throwing an exception as a result.

kind regards
(01-12-2023, 08:57 AM)josemendez Wrote: [ -> ]Some concrete implementations of ObiNativeList<T> override/hide the parameterless constructor, as it's not supposed to do anything even when called by Unity. These are lists of data types that get serialized as part of assets (mainly, actor blueprints).


I'm not sure I understand your explanation, ChangeCapacity is not only called by the list's constructor. It is also called when adding individual elements or a range of elements to the list, basically in any situation that we need to actually store something in the list.

As a result, even if the constructor is not called isCreated will be set true as soon as the list is used for the first time. As far as I can tell, there's no situation in which isCreated can be be false and the safety handle to exist simultaneously, leading to a leak.

However if the constructor is not called (and the safety handle is hence invalid) but Dispose is called, it will attempt to destroy a handle that doesn't exist. This is what Unity does and why making the safety handle destruction code depend on isCreated is correct.

kind regards


Thank you again for your quick response.
Thank you for your detailed answer. I believe I have no further questions.
Pages: 1 2