From 8509fe344e0e5f532680cdfc60199ad632c15218 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Wed, 20 May 2026 14:18:35 +0900 Subject: [PATCH 1/2] Fix NullReferenceException in NUIGadgetManager - Wrap UIGadgetInfo.CreateUIGadgetInfo with try/catch and log packageId on exception - Add try/catch in UIGadgetManager static constructor to prevent TypeInitializationException - Add try/catch in foreach loop to continue loading other packages on failure - Add try/catch in UIGadgetManager.Refresh() with packageId in error logs - Add try/catch in NUIGadgetManager static constructor, LoadGadgetInfos, and Refresh Signed-off-by: Changgyu Choi --- .../Tizen.Applications/UIGadgetInfo.cs | 53 +++++++----- .../Tizen.Applications/UIGadgetManager.cs | 81 ++++++++++++------- .../Tizen.NUI/NUIGadgetManager.cs | 53 ++++++++---- 3 files changed, 121 insertions(+), 66 deletions(-) diff --git a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs index 0c76d05481c..ca975af2ba6 100755 --- a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs +++ b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); @@ -222,31 +222,44 @@ private static void SetResourceType(UIGadgetInfo info, IntPtr handle) internal static UIGadgetInfo CreateUIGadgetInfo(string packageId) { - Interop.PackageManagerInfo.ErrorCode errorCode = Interop.PackageManagerInfo.PackageInfoGet(packageId, out IntPtr handle); - if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) + try { - Log.Error("Failed to get package info. error = " + errorCode); - return null; - } + Interop.PackageManagerInfo.ErrorCode errorCode = Interop.PackageManagerInfo.PackageInfoGet(packageId, out IntPtr handle); + if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) + { + Log.Error("Failed to get package info. packageId: " + packageId + ", error = " + errorCode); + return null; + } + + UIGadgetInfo info = new UIGadgetInfo(packageId); + if (info == null) + { + Log.Error("Failed to create UIGadgetInfo. packageId: " + packageId); + return null; + } - UIGadgetInfo info = new UIGadgetInfo(packageId); + SetResourceType(info, handle); + SetResourceVersion(info, handle); + SetMetadata(info, handle); - SetResourceType(info, handle); - SetResourceVersion(info, handle); - SetMetadata(info, handle); + errorCode = Interop.PackageManagerInfo.PackageInfoDestroy(handle); + if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) + { + Log.Warn("Failed to destroy package info. error = " + errorCode); + } - errorCode = Interop.PackageManagerInfo.PackageInfoDestroy(handle); - if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) + SetExecutableFile(info); + SetResourceFile(info); + SetResourceClassName(info); + SetResourcePath(info); + SetUIGadgetResourcePath(info); + return info; + } + catch (Exception e) { - Log.Warn("Failed to destroy package info. error = " + errorCode); + Log.Error("Exception occurred while creating UIGadgetInfo. packageId: " + packageId + ", exception: " + e); + return null; } - - SetExecutableFile(info); - SetResourceFile(info); - SetResourceClassName(info); - SetResourcePath(info); - SetUIGadgetResourcePath(info); - return info; } } } diff --git a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs index 95d3c6e8dfd..61bb5435596 100755 --- a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs +++ b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs @@ -39,43 +39,57 @@ public static class UIGadgetManager static UIGadgetManager() { - var ptr = Interop.Libc.GetEnvironmentVariable("GADGET_PKGIDS"); - if (ptr != IntPtr.Zero) + try { - var packages = Marshal.PtrToStringAnsi(ptr); - if (!string.IsNullOrWhiteSpace(packages)) + var ptr = Interop.Libc.GetEnvironmentVariable("GADGET_PKGIDS"); + if (ptr != IntPtr.Zero) { - foreach (var pkg in packages.Split(':')) + var packages = Marshal.PtrToStringAnsi(ptr); + if (!string.IsNullOrWhiteSpace(packages)) { - var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); - if (info != null) + foreach (var pkg in packages.Split(':')) { try { - _gadgetInfos.TryAdd(info.ResourceType, info); + var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); + if (info != null) + { + try + { + _gadgetInfos.TryAdd(info.ResourceType, info); + } + catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + { + Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); + } + } } - catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + catch (Exception e) { - Log.Error("Exception occurs. " + e.Message); + Log.Error("Exception occurs while creating gadget info. packageId: " + pkg + ", " + e); } } } } + else + { + Log.Warn("Failed to get environment variable"); + } + + var app = (CoreApplication)CoreApplication.Current; + app.AppControlReceived += (s, e) => HandleAppControl(e); + app.LowMemory += (s, e) => HandleLowMemoryEvent(e); + app.LowBattery += (s, e) => HandleLowBatteryEvent(e); + app.LocaleChanged += (s, e) => HandleLocaleChangedEvent(e); + app.RegionFormatChanged += (s, e) => HandleRegionFormatChangedEvent(e); + app.DeviceOrientationChanged += (s, e) => HandleDeviceOrientationChangedEvent(e); + + UIGadgetLifecycleEventBroker.LifecycleChanged += OnUIGadgetLifecycleChanged; } - else + catch (Exception e) { - Log.Warn("Failed to get environment variable"); + Log.Error("Exception occurs in UIGadgetManager static constructor. " + e); } - - var app = (CoreApplication)CoreApplication.Current; - app.AppControlReceived += (s, e) => HandleAppControl(e); - app.LowMemory += (s, e) => HandleLowMemoryEvent(e); - app.LowBattery += (s, e) => HandleLowBatteryEvent(e); - app.LocaleChanged += (s, e) => HandleLocaleChangedEvent(e); - app.RegionFormatChanged += (s, e) => HandleRegionFormatChangedEvent(e); - app.DeviceOrientationChanged += (s, e) => HandleDeviceOrientationChangedEvent(e); - - UIGadgetLifecycleEventBroker.LifecycleChanged += OnUIGadgetLifecycleChanged; } /// @@ -648,18 +662,25 @@ public static void Refresh() { foreach (var pkg in pkgList.Split(':')) { - var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); - if (info != null) + try { - try - { - _gadgetInfos.TryAdd(info.ResourceType, info); - } - catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); + if (info != null) { - Log.Error("Exception occurs. " + e.Message); + try + { + _gadgetInfos.TryAdd(info.ResourceType, info); + } + catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + { + Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); + } } } + catch (Exception e) + { + Log.Error("Exception occurs while creating gadget info. packageId: " + pkg + ", " + e); + } } } Log.Info("# of Gadget after refresh (" + _gadgetInfos.Count + ")"); diff --git a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs index a960980ff37..2da17d967df 100755 --- a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs +++ b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); @@ -36,26 +36,40 @@ public static class NUIGadgetManager static NUIGadgetManager() { - LoadGadgetInfos(); - UIGadgetLifecycleEventBroker.LifecycleChanged += OnUIGadgetLifecycleChanged; + try + { + LoadGadgetInfos(); + UIGadgetLifecycleEventBroker.LifecycleChanged += OnUIGadgetLifecycleChanged; + } + catch (Exception e) + { + Log.Error("Exception occurs in NUIGadgetManager static constructor. " + e); + } } private static void LoadGadgetInfos() { - foreach (var info in UIGadgetManager.GetUIGadgetInfos()) + try { - try + foreach (var info in UIGadgetManager.GetUIGadgetInfos()) { - var gadgetInfo = new NUIGadgetInfo(info); - if (gadgetInfo != null) + try { - _gadgetInfos.TryAdd(gadgetInfo.ResourceType, gadgetInfo); + var gadgetInfo = new NUIGadgetInfo(info); + if (gadgetInfo != null) + { + _gadgetInfos.TryAdd(gadgetInfo.ResourceType, gadgetInfo); + } + } + catch (Exception e) + { + Log.Error("Exception occurs while creating NUIGadgetInfo. packageId: " + info.PackageId + ", " + e); } } - catch (Exception e) when (e is ArgumentNullException || e is OverflowException) - { - Log.Error("Exception occurs. " + e.Message); - } + } + catch (Exception e) + { + Log.Error("Exception occurs in LoadGadgetInfos. " + e); } } @@ -561,10 +575,17 @@ public static void SendMessage(Bundle message) /// 13 public static void Refresh() { - UIGadgetManager.Refresh(); - _gadgetInfos.Clear(); - LoadGadgetInfos(); - Log.Info("# of Gadget after refresh (" + _gadgetInfos.Count + ")"); + try + { + UIGadgetManager.Refresh(); + _gadgetInfos.Clear(); + LoadGadgetInfos(); + Log.Info("# of Gadget after refresh (" + _gadgetInfos.Count + ")"); + } + catch (Exception e) + { + Log.Error("Exception occurs in NUIGadgetManager.Refresh. " + e); + } } } } From ea1ec4255fb12ac2b18e7920ef1d66d2005f439e Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Wed, 20 May 2026 15:00:49 +0900 Subject: [PATCH 2/2] Apply PR review feedback to UIGadget fix - Use 'as' cast instead of direct cast for CoreApplication.Current with null check - Remove redundant outer try/catch in foreach loops (CreateUIGadgetInfo already handles exceptions internally) - Move PackageInfoDestroy to finally block for proper native handle cleanup - Remove redundant null check after 'new NUIGadgetInfo' operator Co-Authored-By: Cline SR Signed-off-by: Changgyu Choi --- .../Tizen.Applications/UIGadgetInfo.cs | 25 +++---- .../Tizen.Applications/UIGadgetManager.cs | 65 ++++++++----------- .../Tizen.NUI/NUIGadgetManager.cs | 5 +- 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs index ca975af2ba6..eedddd8e039 100755 --- a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs +++ b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetInfo.cs @@ -222,9 +222,10 @@ private static void SetResourceType(UIGadgetInfo info, IntPtr handle) internal static UIGadgetInfo CreateUIGadgetInfo(string packageId) { + IntPtr handle = IntPtr.Zero; try { - Interop.PackageManagerInfo.ErrorCode errorCode = Interop.PackageManagerInfo.PackageInfoGet(packageId, out IntPtr handle); + Interop.PackageManagerInfo.ErrorCode errorCode = Interop.PackageManagerInfo.PackageInfoGet(packageId, out handle); if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) { Log.Error("Failed to get package info. packageId: " + packageId + ", error = " + errorCode); @@ -232,22 +233,11 @@ internal static UIGadgetInfo CreateUIGadgetInfo(string packageId) } UIGadgetInfo info = new UIGadgetInfo(packageId); - if (info == null) - { - Log.Error("Failed to create UIGadgetInfo. packageId: " + packageId); - return null; - } SetResourceType(info, handle); SetResourceVersion(info, handle); SetMetadata(info, handle); - errorCode = Interop.PackageManagerInfo.PackageInfoDestroy(handle); - if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) - { - Log.Warn("Failed to destroy package info. error = " + errorCode); - } - SetExecutableFile(info); SetResourceFile(info); SetResourceClassName(info); @@ -260,6 +250,17 @@ internal static UIGadgetInfo CreateUIGadgetInfo(string packageId) Log.Error("Exception occurred while creating UIGadgetInfo. packageId: " + packageId + ", exception: " + e); return null; } + finally + { + if (handle != IntPtr.Zero) + { + Interop.PackageManagerInfo.ErrorCode errorCode = Interop.PackageManagerInfo.PackageInfoDestroy(handle); + if (errorCode != Interop.PackageManagerInfo.ErrorCode.None) + { + Log.Warn("Failed to destroy package info. error = " + errorCode); + } + } + } } } } diff --git a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs index 61bb5435596..b1cf0bac3ed 100755 --- a/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs +++ b/src/Tizen.Applications.UIGadget/Tizen.Applications/UIGadgetManager.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); @@ -49,24 +49,17 @@ static UIGadgetManager() { foreach (var pkg in packages.Split(':')) { - try + var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); + if (info != null) { - var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); - if (info != null) + try { - try - { - _gadgetInfos.TryAdd(info.ResourceType, info); - } - catch (Exception e) when (e is ArgumentNullException || e is OverflowException) - { - Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); - } + _gadgetInfos.TryAdd(info.ResourceType, info); + } + catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + { + Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); } - } - catch (Exception e) - { - Log.Error("Exception occurs while creating gadget info. packageId: " + pkg + ", " + e); } } } @@ -76,13 +69,16 @@ static UIGadgetManager() Log.Warn("Failed to get environment variable"); } - var app = (CoreApplication)CoreApplication.Current; - app.AppControlReceived += (s, e) => HandleAppControl(e); - app.LowMemory += (s, e) => HandleLowMemoryEvent(e); - app.LowBattery += (s, e) => HandleLowBatteryEvent(e); - app.LocaleChanged += (s, e) => HandleLocaleChangedEvent(e); - app.RegionFormatChanged += (s, e) => HandleRegionFormatChangedEvent(e); - app.DeviceOrientationChanged += (s, e) => HandleDeviceOrientationChangedEvent(e); + var app = CoreApplication.Current as CoreApplication; + if (app != null) + { + app.AppControlReceived += (s, e) => HandleAppControl(e); + app.LowMemory += (s, e) => HandleLowMemoryEvent(e); + app.LowBattery += (s, e) => HandleLowBatteryEvent(e); + app.LocaleChanged += (s, e) => HandleLocaleChangedEvent(e); + app.RegionFormatChanged += (s, e) => HandleRegionFormatChangedEvent(e); + app.DeviceOrientationChanged += (s, e) => HandleDeviceOrientationChangedEvent(e); + } UIGadgetLifecycleEventBroker.LifecycleChanged += OnUIGadgetLifecycleChanged; } @@ -662,24 +658,17 @@ public static void Refresh() { foreach (var pkg in pkgList.Split(':')) { - try + var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); + if (info != null) { - var info = UIGadgetInfo.CreateUIGadgetInfo(pkg); - if (info != null) + try { - try - { - _gadgetInfos.TryAdd(info.ResourceType, info); - } - catch (Exception e) when (e is ArgumentNullException || e is OverflowException) - { - Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); - } + _gadgetInfos.TryAdd(info.ResourceType, info); + } + catch (Exception e) when (e is ArgumentNullException || e is OverflowException) + { + Log.Error("Exception occurs while adding gadget info. packageId: " + pkg + ", " + e.Message); } - } - catch (Exception e) - { - Log.Error("Exception occurs while creating gadget info. packageId: " + pkg + ", " + e); } } } diff --git a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs index 2da17d967df..fcbdf9e5ebb 100755 --- a/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs +++ b/src/Tizen.NUI.Gadget/Tizen.NUI/NUIGadgetManager.cs @@ -56,10 +56,7 @@ private static void LoadGadgetInfos() try { var gadgetInfo = new NUIGadgetInfo(info); - if (gadgetInfo != null) - { - _gadgetInfos.TryAdd(gadgetInfo.ResourceType, gadgetInfo); - } + _gadgetInfos.TryAdd(gadgetInfo.ResourceType, gadgetInfo); } catch (Exception e) {