[Packagemanager] Fix lifetime of callback delegate (#503)
authorjeremy-jang <35089715+jeremy-jang@users.noreply.github.com>
Thu, 4 Oct 2018 23:33:32 +0000 (08:33 +0900)
committersemun-lee <35090067+semun-lee@users.noreply.github.com>
Thu, 4 Oct 2018 23:33:32 +0000 (08:33 +0900)
The callback delegate which is passed to unmanaged code can be
garbage-collected before invoked. So we need to save delegate
in managed code until invoked.

Change-Id: Ie8671fa816242040e0372fdf5bf102d41eaaa3cd
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/Tizen.Applications.PackageManager/Tizen.Applications/Package.cs [changed mode: 0755->0644]
src/Tizen.Applications.PackageManager/Tizen.Applications/PackageManager.cs

old mode 100755 (executable)
new mode 100644 (file)
index e33df18..000be4a
@@ -45,6 +45,9 @@ namespace Tizen.Applications
         private List<string> _privileges;
         private int _installedTime;
 
+        private Dictionary<IntPtr, Interop.PackageManager.PackageManagerSizeInfoCallback> _packageManagerSizeInfoCallbackDict = new Dictionary<IntPtr, Interop.PackageManager.PackageManagerSizeInfoCallback>();
+        private int _callbackId = 0;
+
         private Package(string pkgId)
         {
             _id = pkgId;
@@ -204,9 +207,21 @@ namespace Tizen.Applications
                     var pkgSizeInfo = PackageSizeInformation.GetPackageSizeInformation(sizeInfoHandle);
                     tcs.TrySetResult(pkgSizeInfo);
                 }
+
+                lock (_packageManagerSizeInfoCallbackDict)
+                {
+                    _packageManagerSizeInfoCallbackDict.Remove(userData);
+                }
             };
 
-            Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerGetSizeInfo(Id, sizeInfoCb, IntPtr.Zero);
+            IntPtr callbackId;
+            lock (_packageManagerSizeInfoCallbackDict)
+            {
+                callbackId = (IntPtr)_callbackId++;
+                _packageManagerSizeInfoCallbackDict[callbackId] = sizeInfoCb;
+            }
+
+            Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerGetSizeInfo(Id, sizeInfoCb, callbackId);
             if (err != Interop.PackageManager.ErrorCode.None)
             {
                 tcs.TrySetException(PackageManagerErrorFactory.GetException(err, "Failed to get total package size info of " + Id));
index 80d55d2..c813028 100644 (file)
@@ -43,6 +43,9 @@ namespace Tizen.Applications
 
         private static Interop.PackageManager.PackageManagerEventCallback s_packageManagerEventCallback;
 
+        private static Dictionary<IntPtr, Interop.PackageManager.PackageManagerTotalSizeInfoCallback> s_totalSizeInfoCallbackDict = new Dictionary<IntPtr, Interop.PackageManager.PackageManagerTotalSizeInfoCallback>();
+        private static int s_callbackId = 0;
+
         /// <summary>
         /// Event callback method for the request.
         /// </summary>
@@ -383,15 +386,28 @@ namespace Tizen.Applications
         public static async Task<PackageSizeInformation> GetTotalSizeInformationAsync()
         {
             TaskCompletionSource<PackageSizeInformation> tcs = new TaskCompletionSource<PackageSizeInformation>();
+
             Interop.PackageManager.PackageManagerTotalSizeInfoCallback cb = (handle, userData) =>
             {
                 if (handle != IntPtr.Zero)
                 {
                     tcs.TrySetResult(PackageSizeInformation.GetPackageSizeInformation(handle));
                 }
+
+                lock (s_totalSizeInfoCallbackDict)
+                {
+                    s_totalSizeInfoCallbackDict.Remove(userData);
+                }
             };
 
-            var err = Interop.PackageManager.PackageManagerGetTotalSizeInfo(cb, IntPtr.Zero);
+            IntPtr callbackId;
+            lock (s_totalSizeInfoCallbackDict)
+            {
+                callbackId = (IntPtr)s_callbackId++;
+                s_totalSizeInfoCallbackDict[callbackId] = cb;
+            }
+
+            var err = Interop.PackageManager.PackageManagerGetTotalSizeInfo(cb, callbackId);
             if (err != Interop.PackageManager.ErrorCode.None)
             {
                 tcs.TrySetException(PackageManagerErrorFactory.GetException(err, "Failed to get total package size info"));