← back to Exo
Fix uninstall button error (#1306)
ffacabe7e46191ea08c5d3bb0341d99c19365b42 · 2026-01-29 17:57:48 +0500 · Sami Khan
## Motivation
Fix "Network setup script failed" error when clicking uninstall button
and resolve Xcode compiler warnings.
## Changes
- NetworkSetupHelper.swift: Add || true guards and explicit return 0 in
find_and_enable_thunderbolt_bridge to prevent script failures with set
-euo pipefail
- ThunderboltBridgeService.swift: Use withCString and
withUnsafeMutablePointer for Authorization API calls to fix pointer
lifetime warnings
- EXOApp.swift: Mark showNotification as nonisolated to fix main actor
isolation warning
## Why It Works
- The uninstall script's Thunderbolt re-enable function could exit
non-zero in edge cases (no bridges, no matches). Since this is a cleanup
step, failures should not abort uninstall.
- Swift requires explicit pointer lifetime management when passing
strings/structs to C APIs.
- showNotification is called from a nonisolated delegate method and uses
thread-safe APIs.
## Test Plan
### Manual Testing
Hardware: MacBook Pro
- Clicked Uninstall button, verified it completes without error
- Built in Xcode, verified no warnings
### Automated Testing
N/A
Files touched
M app/EXO/EXO/EXOApp.swiftM app/EXO/EXO/Services/NetworkSetupHelper.swiftM app/EXO/EXO/Services/ThunderboltBridgeService.swift
Diff
commit ffacabe7e46191ea08c5d3bb0341d99c19365b42
Author: Sami Khan <98742866+samiamjidkhan@users.noreply.github.com>
Date: Thu Jan 29 17:57:48 2026 +0500
Fix uninstall button error (#1306)
## Motivation
Fix "Network setup script failed" error when clicking uninstall button
and resolve Xcode compiler warnings.
## Changes
- NetworkSetupHelper.swift: Add || true guards and explicit return 0 in
find_and_enable_thunderbolt_bridge to prevent script failures with set
-euo pipefail
- ThunderboltBridgeService.swift: Use withCString and
withUnsafeMutablePointer for Authorization API calls to fix pointer
lifetime warnings
- EXOApp.swift: Mark showNotification as nonisolated to fix main actor
isolation warning
## Why It Works
- The uninstall script's Thunderbolt re-enable function could exit
non-zero in edge cases (no bridges, no matches). Since this is a cleanup
step, failures should not abort uninstall.
- Swift requires explicit pointer lifetime management when passing
strings/structs to C APIs.
- showNotification is called from a nonisolated delegate method and uses
thread-safe APIs.
## Test Plan
### Manual Testing
Hardware: MacBook Pro
- Clicked Uninstall button, verified it completes without error
- Built in Xcode, verified no warnings
### Automated Testing
N/A
---
app/EXO/EXO/EXOApp.swift | 2 +-
app/EXO/EXO/Services/NetworkSetupHelper.swift | 15 +++++-----
.../EXO/Services/ThunderboltBridgeService.swift | 33 ++++++++++++----------
3 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/app/EXO/EXO/EXOApp.swift b/app/EXO/EXO/EXOApp.swift
index 2ba2c9e8..7669c408 100644
--- a/app/EXO/EXO/EXOApp.swift
+++ b/app/EXO/EXO/EXOApp.swift
@@ -225,7 +225,7 @@ private final class ExoUpdaterDelegate: NSObject, SPUUpdaterDelegate {
}
}
- private func showNotification(title: String, body: String) {
+ nonisolated private func showNotification(title: String, body: String) {
let center = UNUserNotificationCenter.current()
let content = UNMutableNotificationContent()
content.title = title
diff --git a/app/EXO/EXO/Services/NetworkSetupHelper.swift b/app/EXO/EXO/Services/NetworkSetupHelper.swift
index 27d98582..8fc6f97f 100644
--- a/app/EXO/EXO/Services/NetworkSetupHelper.swift
+++ b/app/EXO/EXO/Services/NetworkSetupHelper.swift
@@ -241,11 +241,11 @@ enum NetworkSetupHelper {
rm -f "$LOG_OUT" "$LOG_ERR"
# Switch back to Automatic network location
- networksetup -switchtolocation Automatic 2>/dev/null || true
+ networksetup -switchtolocation Automatic >/dev/null 2>&1 || true
# Delete the exo network location if it exists
- networksetup -listlocations | grep -q '^exo$' && {
- networksetup -deletelocation exo 2>/dev/null || true
+ networksetup -listlocations 2>/dev/null | grep -q '^exo$' && {
+ networksetup -deletelocation exo >/dev/null 2>&1 || true
} || true
# Re-enable any Thunderbolt Bridge service if it exists
@@ -255,12 +255,12 @@ enum NetworkSetupHelper {
tb_devices=$(networksetup -listallhardwareports 2>/dev/null | awk '
/^Hardware Port:/ { port = tolower(substr($0, 16)) }
/^Device:/ { if (port ~ /thunderbolt/) print substr($0, 9) }
- ')
+ ') || true
[ -z "$tb_devices" ] && return 0
# For each bridge device, check if it contains Thunderbolt interfaces
for bridge in bridge0 bridge1 bridge2; do
- members=$(ifconfig "$bridge" 2>/dev/null | awk '/member:/ {print $2}')
+ members=$(ifconfig "$bridge" 2>/dev/null | awk '/member:/ {print $2}') || true
[ -z "$members" ] && continue
for tb_dev in $tb_devices; do
@@ -269,7 +269,7 @@ enum NetworkSetupHelper {
service_name=$(networksetup -listnetworkserviceorder 2>/dev/null | awk -v dev="$bridge" '
/^\\([0-9*]/ { gsub(/^\\([0-9*]+\\) /, ""); svc = $0 }
/Device:/ && $0 ~ dev { print svc; exit }
- ')
+ ') || true
if [ -n "$service_name" ]; then
networksetup -setnetworkserviceenabled "$service_name" on 2>/dev/null || true
return 0
@@ -277,8 +277,9 @@ enum NetworkSetupHelper {
fi
done
done
+ return 0
}
- find_and_enable_thunderbolt_bridge
+ find_and_enable_thunderbolt_bridge || true
echo "EXO network components removed successfully"
"""
diff --git a/app/EXO/EXO/Services/ThunderboltBridgeService.swift b/app/EXO/EXO/Services/ThunderboltBridgeService.swift
index c9b11454..112fb991 100644
--- a/app/EXO/EXO/Services/ThunderboltBridgeService.swift
+++ b/app/EXO/EXO/Services/ThunderboltBridgeService.swift
@@ -127,21 +127,24 @@ final class ThunderboltBridgeService: ObservableObject {
// 2. Request specific network configuration rights
let rightName = "system.services.systemconfiguration.network"
- var item = AuthorizationItem(
- name: rightName,
- valueLength: 0,
- value: nil,
- flags: 0
- )
- var rights = AuthorizationRights(count: 1, items: &item)
-
- status = AuthorizationCopyRights(
- authRef,
- &rights,
- nil,
- [.extendRights, .interactionAllowed],
- nil
- )
+ status = rightName.withCString { nameCString in
+ var item = AuthorizationItem(
+ name: nameCString,
+ valueLength: 0,
+ value: nil,
+ flags: 0
+ )
+ return withUnsafeMutablePointer(to: &item) { itemPointer in
+ var rights = AuthorizationRights(count: 1, items: itemPointer)
+ return AuthorizationCopyRights(
+ authRef,
+ &rights,
+ nil,
+ [.extendRights, .interactionAllowed],
+ nil
+ )
+ }
+ }
guard status == errAuthorizationSuccess else {
if status == errAuthorizationCanceled {
throw ThunderboltBridgeError.authorizationCanceled
← 9e58a575 Add RDMA caveats to README.md (#1316)
·
back to Exo
·
Add startup delay and update network setup message (#1309) 91115759 →