-
Notifications
You must be signed in to change notification settings - Fork 275
[AI Task] [Tizen.Network.WiFi] Consolidate GetFound*/GetWiFiConfigurations into EnumerateForeach<T> helper#7680
[AI Task] [Tizen.Network.WiFi] Consolidate GetFound*/GetWiFiConfigurations into EnumerateForeach<T> helper #7680JoonghyunCho wants to merge 2 commits into
Conversation
... EnumerateForeach<T> helper GetFoundAPs, GetFoundSpecificAPs, GetFoundBssids and GetWiFiConfigurations each repeated the same 'native foreach callback -> List collection' pattern, differing only by the native foreach function, the handle clone call, and the wrapper type. Introduces a generic EnumerateForeach<T> helper that takes the operation name, privilege, native foreach function, and an item-wrap delegate. The wrap delegate absorbs the differing Clone signatures (AP.Clone has the out handle first; Config.Clone has it second). Iteration semantics, ret-check timing, exception mapping (CheckReturnValue) and per-method privilege are preserved, so behavior is unchanged. Fixes #7622
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request refactors the GetFoundAPs, GetFoundSpecificAPs, GetFoundBssids, and GetWiFiConfigurations methods by introducing a shared helper method, EnumerateForeach<T>, to eliminate code duplication when iterating over native handles. The feedback recommends catching and safely rethrowing exceptions within the native callback to prevent undefined behavior from propagating managed exceptions across P/Invoke boundaries. Additionally, the reviewer advises checking the return values of the native clone operations (Interop.WiFi.AP.Clone and Interop.WiFi.Config.Clone) to handle potential cloning failures gracefully.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Propagating managed exceptions through native code boundaries (P/Invoke) can lead to undefined behavior, native crashes, or silent failures. Since the wrap delegate can throw exceptions (e.g., if cloning fails or during object construction), it is highly recommended to catch any exceptions inside the callback, stop the iteration, and safely rethrow the captured exception after the native foreach method returns.
private List<T> EnumerateForeach<T>(string opName, string privilege, Func<SafeWiFiManagerHandle, Interop.WiFi.HandleCallback, IntPtr, int> nativeForeach, Func<IntPtr, T> wrap) { Log.Info(Globals.LogTag, opName); List<T> list = new List<T>(); Exception capturedException = null; Interop.WiFi.HandleCallback callback = (IntPtr handle, IntPtr userData) => { if (handle != IntPtr.Zero) { try { list.Add(wrap(handle)); } catch (Exception ex) { capturedException = ex; return false; } return true; } return false; }; int ret = nativeForeach(GetSafeHandle(), callback, IntPtr.Zero); if (capturedException != null) { throw capturedException; } CheckReturnValue(ret, opName, privilege); return list; }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of Interop.WiFi.AP.Clone is ignored. If cloning fails, it may return a non-zero error code and leave clonedHandle as IntPtr.Zero or invalid, which will cause downstream failures when the WiFiAP instance is used. It is safer to check the return value and throw an exception if cloning fails.
apHandle => { int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); if (ret != (int)WiFiError.None) { WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); } return new WiFiAP(clonedHandle); });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of Interop.WiFi.AP.Clone is ignored. If cloning fails, it may return a non-zero error code and leave clonedHandle as IntPtr.Zero or invalid, which will cause downstream failures when the WiFiAP instance is used. It is safer to check the return value and throw an exception if cloning fails.
apHandle => { int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); if (ret != (int)WiFiError.None) { WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); } return new WiFiAP(clonedHandle); });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of Interop.WiFi.AP.Clone is ignored. If cloning fails, it may return a non-zero error code and leave clonedHandle as IntPtr.Zero or invalid, which will cause downstream failures when the WiFiAP instance is used. It is safer to check the return value and throw an exception if cloning fails.
apHandle => { int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); if (ret != (int)WiFiError.None) { WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); } return new WiFiAP(clonedHandle); });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of Interop.WiFi.Config.Clone is ignored. If cloning fails, it may return a non-zero error code and leave clonedConfig as IntPtr.Zero or invalid, which will cause downstream failures when the WiFiConfiguration instance is used. It is safer to check the return value and throw an exception if cloning fails.
configHandle => { int ret = Interop.WiFi.Config.Clone(configHandle, out IntPtr clonedConfig); if (ret != (int)WiFiError.None) { WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone WiFi configuration"); } return new WiFiConfiguration(clonedConfig); });
JoonghyunCho
commented
Jun 7, 2026
🤖 [AI Review]
Reviewed — no findings.
Scope checked:
- All 4 converted methods (
GetFoundAPs,GetFoundSpecificAPs,GetFoundBssids,GetWiFiConfigurations) keep their originalCheckReturnValueoperation name and privilege —PrivilegeNetworkGetfor the 3 AP/Bssid getters,PrivilegeNetworkProfilefor configurations. - The two divergent native clone signatures are correctly absorbed by the
wrapdelegate:AP.Clone(out cloned, original)vsConfig.Clone(origin, out cloned)— arg order preserved per call site. - Callback contract is identical: wraps + adds the item and returns
truefor a non-zero handle,falseotherwise. GetSafeHandle()is still resolved once per call, immediately before the native foreach.- All 4 methods are
internaland the generic helper isprivate→ no public API surface, so no XML-doc/since_tizen obligation.
No 🔴 critical issues, no 🟡 suggestions to flag.
Automated review — final merge decision rests with human reviewers.
Harden EnumerateForeach<T>: catch exceptions raised inside the native foreach callback so they never unwind across the P/Invoke boundary, and rethrow after the native call returns. Check the return value of every AP.Clone / Config.Clone call and throw a WiFiException when cloning fails. Applied-Human-Comments: 3369222130,3369222132,3369222133,3369222134,3369222136
JoonghyunCho
commented
Jun 8, 2026
🤖 [AI Review]
Addressed review feedback in commit 37941b2. Summary: EnumerateForeach<T> now wraps the per-item wrap call in a try/catch, captures any exception, stops the iteration, and rethrows it after the native foreach returns so a managed exception never unwinds across the P/Invoke boundary. In addition, every AP.Clone / Config.Clone call now checks its return value and throws a WiFiException (via WiFiErrorFactory.ThrowWiFiException) when cloning fails.
Summary
Consolidates the four near-identical "native foreach callback →
Listcollection" methods inWiFiManagerImplinto a single genericEnumerateForeach<T>helper.Changes
src/Tizen.Network.WiFi/Tizen.Network.WiFi/WiFiManagerImpl.csEnumerateForeach<T>(opName, privilege, nativeForeach, wrap)helper.GetFoundAPs,GetFoundSpecificAPs,GetFoundBssids,GetWiFiConfigurations.Behavior preservation
truefor a non-zero handle, and returnsfalseotherwise.CheckReturnValueis still called immediately after the native foreach returns, with the same operation name and the same per-method privilege (PrivilegeNetworkGetfor the AP/Bssid getters,PrivilegeNetworkProfilefor configurations).wrapdelegate absorbs the differing clone signatures:Interop.WiFi.AP.Clone(out cloned, original)vsInterop.WiFi.Config.Clone(origin, out cloned).internal).Mode
Refactoring (behavior-preserving)
Verification
dotnet build src/Tizen.Network.WiFi/Tizen.Network.WiFi.csproj -c Release, 0 errors / 0 warnings)sdbdevice connected —sdb devicesreports no targets; manual benchmark verification required)Fixes #7622