[MachineLearning.Train] Change internal logic to resolve a memory leak
authorSeoHyungjun <hyungjun.seo@samsung.com>
Fri, 4 Oct 2024 08:17:00 +0000 (17:17 +0900)
committerSW Kim <sw0312.kim@samsung.com>
Tue, 15 Oct 2024 07:50:58 +0000 (16:50 +0900)
There were issues with heap use after free and heap overflow occurring
(TNINE-4152, 4153, 4154).

In order to solve this problem, modified the internal logic of the API.

Signed-off-by: SeoHyungjun <hyungjun.seo@samsung.com>
src/Tizen.MachineLearning.Train/Tizen.MachineLearning.Train/Dataset.cs
src/Tizen.MachineLearning.Train/Tizen.MachineLearning.Train/Layer.cs
src/Tizen.MachineLearning.Train/Tizen.MachineLearning.Train/Model.cs
src/Tizen.MachineLearning.Train/Tizen.MachineLearning.Train/Optimizer.cs

index cfaf094c2a0ceedee78232318e7553c7633bf86c..5658d4faa8e3612bdce2c1b915f2026b0a2eb4df 100644 (file)
@@ -37,6 +37,9 @@ namespace Tizen.MachineLearning.Train
         private IntPtr handle = IntPtr.Zero;
         private bool disposed = false;
 
+        /// if false, model will be destroy dataset handle
+        private bool hasOwnership = true;
+
         /// <summary>
         ///  Constructs the dataset.
         /// </summary>
@@ -44,6 +47,9 @@ namespace Tizen.MachineLearning.Train
         public Dataset()
         {
             NNTrainerError ret = Interop.Dataset.Create(out handle);
+            if (ret != NNTrainerError.None) {
+                handle = IntPtr.Zero;
+            }
             NNTrainer.CheckException(ret, "Failed to create dataset instance");
             Log.Info(NNTrainer.Tag, "Create Dataset");
         }
@@ -82,6 +88,14 @@ namespace Tizen.MachineLearning.Train
             {
                 // release managed object
             }
+
+            disposed = true;
+
+            if (!hasOwnership){
+                Log.Info(NNTrainer.Tag, "Cannot destroy dataset already added in a Model. Model will destroy this dataset");
+                return;
+            }
+
             // release unmanaged object
             if (handle != IntPtr.Zero)
             {
@@ -92,7 +106,6 @@ namespace Tizen.MachineLearning.Train
 
                 handle = IntPtr.Zero;
             }
-            disposed = true;
         }
 
         /// <summary>
@@ -124,6 +137,11 @@ namespace Tizen.MachineLearning.Train
             return handle;
         }
 
+        internal void RemoveOwnership()
+        {
+            this.hasOwnership = false;
+        }
+
         /// <summary>
         /// Sets the neural network dataset property.
         /// </summary>
index 8f66059aa7da7bd307759830d3c303d21558939a..db19839f520763c7972f234e675e6d82814dcf93 100644 (file)
@@ -49,6 +49,9 @@ namespace Tizen.MachineLearning.Train
         public Layer(NNTrainerLayerType type)
         {
             NNTrainerError ret = Interop.Layer.Create(out handle, type);
+            if (ret != NNTrainerError.None) {
+                handle = IntPtr.Zero;
+            }
             NNTrainer.CheckException(ret, "Failed to create model instance");
             Log.Info(NNTrainer.Tag, $"Create layer with type:{type}");
         }
@@ -98,7 +101,7 @@ namespace Tizen.MachineLearning.Train
             disposed = true;
 
             if (!hasOwnership){
-                Log.Error(NNTrainer.Tag, "Cannot destroy layer already added in a Model. Model will destroy this layer");
+                Log.Info(NNTrainer.Tag, "Cannot destroy layer already added in a Model. Model will destroy this layer");
                 return;
             }
 
index d92636e0f57fdd8847c43c373a42823caea07eec..fa6a86fa44ec4dba8eec6ac0072cdbeb262c3819 100644 (file)
@@ -65,6 +65,9 @@ namespace Tizen.MachineLearning.Train
                 NNTrainer.CheckException(NNTrainerError.InvalidParameter, "modelConf is null");
 
             NNTrainerError ret = Interop.Model.ConstructWithConf(modelConf, out handle);
+            if (ret != NNTrainerError.None) {
+                handle = IntPtr.Zero;
+            }
             NNTrainer.CheckException(ret, "Failed to create model instance with modelConf");
             Log.Info(NNTrainer.Tag, "Created Model with Conf path: "+ modelConf);
         }
@@ -281,7 +284,7 @@ namespace Tizen.MachineLearning.Train
         public Layer GetLayer(string layerName)
         {
             IntPtr layerHandle = IntPtr.Zero;
-             if (string.IsNullOrEmpty(layerName))
+            if (string.IsNullOrEmpty(layerName))
                 NNTrainer.CheckException(NNTrainerError.InvalidParameter, "layerName is null");
 
             NNTrainerError ret = Interop.Model.GetLayer(handle, layerName, out layerHandle);
@@ -311,6 +314,7 @@ namespace Tizen.MachineLearning.Train
 
             NNTrainerError ret = Interop.Model.SetOptimizer(handle, optimizer.GetHandle());
             NNTrainer.CheckException(ret, "Failed to set optimizer");
+            optimizer.RemoveOwnership();
         }
 
         /// <summary>
@@ -335,6 +339,7 @@ namespace Tizen.MachineLearning.Train
 
             NNTrainerError ret = Interop.Model.SetDataset(handle, dataset.GetHandle());
             NNTrainer.CheckException(ret, "Failed to set dataset");
+            dataset.RemoveOwnership();
         }
 
         internal static TensorsInfo CreateTensorsInfoFormHandle(IntPtr handle)
index de7bdf389c3037ab3a29b0a4a16baec94d8f5b35..e10174e3d1827f17247e64bd2465acb14b0f6751 100644 (file)
@@ -37,6 +37,9 @@ namespace Tizen.MachineLearning.Train
         private IntPtr handle = IntPtr.Zero;
         private bool disposed = false;
 
+        /// if false, model will be destroy optimizer handle
+        private bool hasOwnership = true;
+
         /// <summary>
         /// Creates a neural network optimizer.
         /// </summary>
@@ -45,6 +48,9 @@ namespace Tizen.MachineLearning.Train
         public Optimizer(NNTrainerOptimizerType type)
         {
             NNTrainerError ret = Interop.Optimizer.Create(out handle, type);
+            if (ret != NNTrainerError.None) {
+                handle = IntPtr.Zero;
+            }
             NNTrainer.CheckException(ret, "Failed to create optimizer instance");
             Log.Info(NNTrainer.Tag, $"Create optimizer with type:{type}");
         }
@@ -83,6 +89,14 @@ namespace Tizen.MachineLearning.Train
             {
                 // release managed object
             }
+
+            disposed = true;
+
+            if (!hasOwnership){
+                Log.Info(NNTrainer.Tag, "Cannot destroy optimizer already added in a Model. Model will destroy this optimizer");
+                return;
+            }
+
             // release unmanaged object
             if (handle != IntPtr.Zero)
             {
@@ -93,7 +107,6 @@ namespace Tizen.MachineLearning.Train
 
                 handle = IntPtr.Zero;
             }
-            disposed = true;
         }
 
         /// <summary>
@@ -122,5 +135,10 @@ namespace Tizen.MachineLearning.Train
         {
             return handle;
         }
+
+        internal void RemoveOwnership()
+        {
+            this.hasOwnership = false;
+        }
     } 
 }