[NUI] fix testhub fail, Add Dispose() in BaseHandle.Reset() where the body was delete...
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Common / BaseHandle.cs
old mode 100644 (file)
new mode 100755 (executable)
index c033810..f221e0a
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ using System;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
 using Tizen.NUI.Binding;
+using global::System.Diagnostics;
 
 namespace Tizen.NUI
 {
@@ -31,15 +32,15 @@ namespace Tizen.NUI
         /// swigCMemOwn
         /// </summary>
         /// <since_tizen> 3 </since_tizen>
-        [Obsolete("Deprecated in API9, Will be removed in API11, Please use SwigCMemOwn")]
+        [Obsolete("Deprecated in API9, will be removed in API11, Use SwigCMemOwn")]
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "<Pending>")]
         protected bool swigCMemOwn;
 
         /// <summary>
-        /// A flag to check if it is already disposed.
+        /// The flag to check if it is already disposed of.
         /// </summary>
         /// <since_tizen> 3 </since_tizen>
-        [Obsolete("Deprecated in API9, Will be removed in API11, Please use Disposed")]
+        [Obsolete("Deprecated in API9, will be removed in API11, Use Disposed")]
         [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "<Pending>")]
         protected bool disposed = false;
 
@@ -47,7 +48,7 @@ namespace Tizen.NUI
         private global::System.Runtime.InteropServices.HandleRef swigCPtrCopy;
         private bool registerMe;
 
-        //A Flag to check who called Dispose(). (By User or DisposeQueue)
+        //The flag to check who called Dispose(). (By User or DisposeQueue)
         private bool isDisposeQueued = false;
 
         /// <summary>
@@ -88,11 +89,7 @@ namespace Tizen.NUI
                 Registry.Register(this);
             }
 
-            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-            if (this is BaseComponents.View view)
-            {
-                  DebugFileLogging.Instance.WriteLog($"ID:{view.ID} Name:{view.Name}");
-            }
+            disposeDebuggingCtor();
             DebugFileLogging.Instance.WriteLog($" BaseHandle.contructor with cMemeryOwn END");
             DebugFileLogging.Instance.WriteLog($"=============================");
         }
@@ -115,11 +112,7 @@ namespace Tizen.NUI
                 Registry.Register(this);
             }
 
-            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-            if (this is BaseComponents.View view)
-            {
-                DebugFileLogging.Instance.WriteLog($"ID:{view.ID} Name:{view.Name}");
-            }
+            disposeDebuggingCtor();
             DebugFileLogging.Instance.WriteLog($"BaseHandle.contructor END");
             DebugFileLogging.Instance.WriteLog($"=============================");
         }
@@ -136,7 +129,7 @@ namespace Tizen.NUI
         /// </summary>
         /// <since_tizen> 5 </since_tizen>
         /// <seealso cref="BindableObject.PropertyChanged"/>
-        [Obsolete("Deprecated in API9, Will be removed in API11, Please use BindableObject.PropertyChanged instead!")]
+        [Obsolete("Deprecated in API9, will be removed in API11, Use BindableObject.PropertyChanged instead.")]
         public event PropertyChangedEventHandler PropertySet;
 
         internal global::System.Runtime.InteropServices.HandleRef GetBaseHandleCPtrHandleRef
@@ -356,15 +349,22 @@ namespace Tizen.NUI
                     DebugFileLogging.Instance.WriteLog("[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");
 
-                    throw new global::System.InvalidOperationException("[NUI][BaseHandle] This API called from separate thread. This API must be called from MainThread. \n" +
+                    Tizen.Log.Fatal("NUI", $"[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");
+
+                    //to fix ArtApp black screen issue. this will be enabled after talking with ArtApp team and fixing it.
+                    // 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");
                 }
 
                 if (isDisposeQueued)
                 {
                     DebugFileLogging.Instance.WriteLog($"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!");
+                    Tizen.Log.Fatal("NUI", $"[NUI] should not be here! (dead code) this will be removed!");
+
+                    //to fix ArtApp black screen issue. this will be enabled after talking with ArtApp team and fixing it.
+                    // throw new global::System.Exception($"[NUI] should not be here! (dead code) this will be removed!");
                     Dispose(DisposeTypes.Implicit);
                 }
                 else
@@ -432,10 +432,13 @@ namespace Tizen.NUI
         /// Resets the handle.
         /// </summary>
         /// <since_tizen> 3 </since_tizen>
+        /// <remark>
+        /// This will be deprecated, please use Dispose() instead.
+        /// </remark>
         public void Reset()
         {
-            Interop.BaseHandle.Reset(swigCPtrCopy);
-            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            this.Dispose();
+            NUILog.Error("[ERROR] This(BaseHandle.Reset) will be deprecated, please use Dispose() instead!");
         }
 
         /// <summary>
@@ -493,7 +496,7 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public bool IsEqual(BaseHandle rhs)
         {
-            if (disposed == true)
+            if (disposed == true || rhs == null || !rhs.HasBody())
             {
                 return false;
             }
@@ -544,39 +547,7 @@ namespace Tizen.NUI
                 Registry.Unregister(this);
             }
 
-            DebugFileLogging.Instance.WriteLog($"swigCMemOwn:{swigCMemOwn} type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
-
-            // 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)
-                        {
-                            DebugFileLogging.Instance.WriteLog($"[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}");
-
-                            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}");
-                        }
-                    }
-                }
-            }
+            disposeDebuggingDispose(type);
 
             if (SwigCPtr.Handle != IntPtr.Zero)
             {
@@ -608,11 +579,6 @@ namespace Tizen.NUI
             }
 
             disposed = true;
-
-            if (null != Application.Current)
-            {
-                Application.Current.XamlResourceChanged -= OnResourcesChanged;
-            }
             DebugFileLogging.Instance.WriteLog($"BaseHandle.Dispose({type}) END");
             DebugFileLogging.Instance.WriteLog($"=============================");
             NUILog.Debug($"BaseHandle.Dispose({type}) END");
@@ -657,9 +623,23 @@ namespace Tizen.NUI
                     var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
                     var me = this.GetType().FullName;
 
-                    throw new ObjectDisposedException(nameof(SwigCPtr), $"Error! NUI's native dali object is already disposed. " +
+                    Tizen.Log.Fatal("NUI", $"SwigCPtr Error! NUI's native dali object is already disposed. " +
                         $"OR the native dali object handle of NUI becomes null! \n" +
                         $" process:{process} thread:{thread}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n");
+
+                    Tizen.Log.Fatal("NUI", $"[ERROR] back trace!");
+                    global::System.Diagnostics.StackTrace st = new global::System.Diagnostics.StackTrace(true);
+                    for (int i = 0; i < st.FrameCount; i++)
+                    {
+                        global::System.Diagnostics.StackFrame sf = st.GetFrame(i);
+                        Tizen.Log.Fatal("NUI", " Method " + sf.GetMethod());
+                    }
+                    Tizen.Log.Fatal("NUI", "Error! just return here with null swigCPtr! this can cause unknown error or crash in next step");
+
+                    //to fix ArtApp black screen issue. this will be enabled after talking with ArtApp team and fixing it.
+                    // throw new ObjectDisposedException(nameof(SwigCPtr), $"Error! NUI's native dali object is already disposed. " +
+                    //     $"OR the native dali object handle of NUI becomes null! \n" +
+                    //     $" process:{process} thread:{thread}, isDisposed:{this.disposed}, isDisposeQueued:{this.isDisposeQueued}, me:{me}\n");
                 }
                 return swigCPtr;
             }
@@ -677,16 +657,69 @@ namespace Tizen.NUI
         protected internal bool SwigCMemOwn => swigCMemOwn;
 
         /// <summary>
-        /// A flag to check if it is already disposed.
+        /// The flag to check if it is already disposed of.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected internal bool Disposed => disposed;
 
         /// <summary>
-        /// A flag to check if it is disposed by DisposeQueue.
+        /// The flag to check if it is disposed by DisposeQueue.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected internal bool IsDisposeQueued => isDisposeQueued;
 
+        [Conditional("NUI_DISPOSE_DEBUG_ON")]
+        private void disposeDebuggingCtor()
+        {
+            DebugFileLogging.Instance.WriteLog($"type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")}");
+            if (this is BaseComponents.View view)
+            {
+                DebugFileLogging.Instance.WriteLog($"ID:{view.ID} Name:{view.Name}");
+                //back trace
+                global::System.Diagnostics.StackTrace st = new global::System.Diagnostics.StackTrace(true);
+                for (int i = 0; i < st.FrameCount; i++)
+                {
+                    global::System.Diagnostics.StackFrame sf = st.GetFrame(i);
+                    DebugFileLogging.Instance.WriteLog($"[{i}] {sf.GetMethod()}");
+                }
+            }
+        }
+
+        [Conditional("NUI_DISPOSE_DEBUG_ON")]
+        private void disposeDebuggingDispose(DisposeTypes type)
+        {
+            DebugFileLogging.Instance.WriteLog($"swigCMemOwn:{swigCMemOwn} type:{GetType()} copyNativeHandle:{swigCPtrCopy.Handle.ToString("X8")} HasBody:{HasBody()}");
+
+            if (swigCPtr.Handle != IntPtr.Zero && swigCPtrCopy.Handle != IntPtr.Zero && HasBody())
+            {
+                using var currentProcess = global::System.Diagnostics.Process.GetCurrentProcess();
+                var process = currentProcess.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)
+                    {
+                        DebugFileLogging.Instance.WriteLog($"[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}");
+
+                        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}");
+                    }
+                }
+            }
+        }
+
     }
 }