From 61dae4b087bbc386627106acb029bdd67300bc70 Mon Sep 17 00:00:00 2001 From: "dongsug.song" Date: Wed, 17 Nov 2021 14:27:52 +0900 Subject: [PATCH] [NUI] Add some debug log to check reference count of disposed object --- src/Tizen.NUI/src/internal/Common/Disposable.cs | 9 +++++- src/Tizen.NUI/src/public/Common/BaseHandle.cs | 40 ++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/Tizen.NUI/src/internal/Common/Disposable.cs b/src/Tizen.NUI/src/internal/Common/Disposable.cs index aa9d546..9388d9a 100644 --- a/src/Tizen.NUI/src/internal/Common/Disposable.cs +++ b/src/Tizen.NUI/src/internal/Common/Disposable.cs @@ -109,11 +109,18 @@ namespace Tizen.NUI //Throw exception if Dispose() is called in separate thread. if (!Window.IsInstalled()) { - throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread."); + var process = global::System.Diagnostics.Process.GetCurrentProcess().Id; + var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId; + var me = this.GetType().FullName; + + throw new global::System.InvalidOperationException("[NUI][Disposable]This API called from separate thread. This API must be called from MainThread. \n" + + $" process:{process} thread:{thread}, disposing:{disposing}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n"); } if (isDisposeQueued) { + Tizen.Log.Fatal("NUI", $"[Disposable]should not be here! (dead code) this will be removed!"); + throw new global::System.Exception($"[NUI] should not be here! (dead code) this will be removed!"); Dispose(DisposeTypes.Implicit); } else diff --git a/src/Tizen.NUI/src/public/Common/BaseHandle.cs b/src/Tizen.NUI/src/public/Common/BaseHandle.cs index ec2248b..9842020 100644 --- a/src/Tizen.NUI/src/public/Common/BaseHandle.cs +++ b/src/Tizen.NUI/src/public/Common/BaseHandle.cs @@ -366,7 +366,7 @@ namespace Tizen.NUI var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId; var me = this.GetType().FullName; - throw new global::System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread. \n" + + throw new global::System.InvalidOperationException("[NUI][BaseHandle] This API called from separate thread. This API must be called from MainThread. \n" + $" process:{process} thread:{thread}, disposing:{disposing}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n"); } @@ -557,6 +557,33 @@ namespace Tizen.NUI debuggingCount--; NUILog.Debug($"[Dispose] swigCMemOwn:{swigCMemOwn} debuggingCount:{debuggingCount} type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}"); #endif + // this is temporary test code. will be removed laster + { + if (swigCPtr.Handle != IntPtr.Zero && swigCPtrCopy.Handle != IntPtr.Zero) + { + var process = global::System.Diagnostics.Process.GetCurrentProcess().Id; + var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId; + var me = this.GetType().FullName; + var daliId = "unknown"; + var hash = this.GetType().GetHashCode(); + var name = "unknown"; + + if (this is BaseComponents.View) + { + daliId = Interop.Actor.GetId(swigCPtrCopy).ToString(); + name = Interop.Actor.GetName(swigCPtrCopy); + BaseObject tmp = new BaseObject(Interop.BaseHandle.GetBaseObject(swigCPtrCopy), false); + var refCnt = tmp.ReferenceCount(); + tmp.Dispose(); + if (refCnt > 2) + { + Log.Error("NUI", $"[ERR] reference count is over than 2. Could be a memory leak. Need to check! \n" + + $" process:{process} thread:{thread}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me} \n" + + $" disposeType:{type}, name:{name}, daliID:{daliId}, hash:{hash}, refCnt:{refCnt}"); + } + } + } + } if (SwigCPtr.Handle != IntPtr.Zero) { @@ -567,12 +594,23 @@ namespace Tizen.NUI } swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } + else + { + var me = this.GetType().FullName; + Log.Error("NUI", $"[ERR] SwigCPtr is NULL, need to check! me:{me}"); + } + if (swigCPtrCopy.Handle != global::System.IntPtr.Zero) { swigCMemOwn = false; Interop.BaseHandle.DeleteBaseHandle(swigCPtrCopy); swigCPtrCopy = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); } + else + { + var me = this.GetType().FullName; + Log.Error("NUI", $"[ERR] swigCPtrCopy is NULL, need to check! me:{me}"); + } disposed = true; -- 2.7.4