Post not yet marked as solved
With following code:
do {
// (1) loads correct configuration from device's settings
try await NEDNSSettingsManager.shared().loadFromPreferences()
// (2) let's break the configuration
NEDNSSettingsManager.shared().dnsSettings = nil
// (3) this will throw an error because of empty settings
try await NEDNSSettingsManager.shared().saveToPreferences()
} catch {
// (4) doesn't load the same configuration as in (1),
try await NEDNSSettingsManager.shared().loadFromPreferences()
// (5) this will be true, because (4) doesn't do what it is supposed to do
let isInvalid = NEDNSSettingsManager.shared().dnsSettings == nil
throw error
}
The NEDNSSettingsManager instance can't be restored to its last working setting. Isn't loadFromPreferences supposed to do so? Or maybe async-await variant is broken?
I know the code (2) isn't the best way to use the manager, but what if there is some other kind of error during the save process and I want to revert the manager's settings?
Post not yet marked as solved
I have following `NWUDPSession`'s wrapper which handles my network traffic in packet tunnel provider extension:class UDPSession: NSObject {
private var lock = NSLock()
private var session: NWUDPSession?
var onDataReceived: ([Data]) -> Void = {_ in }
init(withProvider provider: NEProvider?, address: String, port: String) {
super.init()
let endpoint = NWHostEndpoint(hostname: address, port: port)
let session = provider?.createUDPSession(to: endpoint, from: nil)
self.session = session
self.setReadHandler()
}
deinit {
cleanup()
}
func send(_ datagram: Data) -> Void {
let currentSession = session
currentSession?.writeDatagram(datagram) { [weak self, weak currentSession] (error) in
if error != nil {
self?.restartSession(currentSession)
return
}
}
}
private func cleanup() {
lock.lock()
defer {
lock.unlock()
}
session?.cancel()
}
private func setReadHandler() {
session?.setReadHandler({ [weak self] (datagrams, error) in
guard let data = datagrams else {
return
}
self?.onDataReceived(data)
}, maxDatagrams: 1)
}
private func restartSession(_ failedSession: NWUDPSession?) {
lock.lock()
defer {
lock.unlock()
}
let currentSession = session
guard let sessionToUpgrade = failedSession, sessionToUpgrade === currentSession else {
return
}
session = NWUDPSession(upgradeFor: sessionToUpgrade)
setReadHandler()
}
}Using Firebase crashlytics in my network extension I noticed the process crashes quite often. Usually the stack trace looks like this:EXC_BAD_ACCESS KERN_PROTECTION_FAILURE 0x0000000105563f20Crashed: com.apple.network.connections
0 libnetwork.dylib 0x1bc436b90 __nw_protocol_udp_finalize_output_frames_block_invoke + 864
1 libnetwork.dylib 0x1bc433b94 nw_protocol_udp_finalize_output_frames + 128
2 libnetwork.dylib 0x1bc4dd17c nw_flow_prepare_output_frames + 7808
3 libnetwork.dylib 0x1bc4daa98 nw_flow_service_writes + 1276
4 libnetwork.dylib 0x1bc4da11c nw_endpoint_handler_service_writes + 100
5 libnetwork.dylib 0x1bc51ceec __nw_connection_batch_block_invoke + 1248
6 libdispatch.dylib 0x1b9cbe610 _dispatch_call_block_and_release + 24
7 libdispatch.dylib 0x1b9cbf184 _dispatch_client_callout + 16
8 libdispatch.dylib 0x1b9c6d0b0 _dispatch_workloop_invoke$VARIANT$mp + 2104
9 libdispatch.dylib 0x1b9c75314 _dispatch_workloop_worker_thread + 588
10 libsystem_pthread.dylib 0x1b9d0eb88 _pthread_wqthread + 276
11 libsystem_pthread.dylib 0x1b9d11760 start_wqthread + 8com.apple.main-thread
0 libsystem_kernel.dylib 0x1b9dc8634 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1b9dc7aa0 mach_msg + 72
2 CoreFoundation 0x1b9f70288 __CFRunLoopServiceMachPort + 216
3 CoreFoundation 0x1b9f6b3a8 __CFRunLoopRun + 1444
4 CoreFoundation 0x1b9f6aadc CFRunLoopRunSpecific + 464
5 Foundation 0x1ba2aa784 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 228
6 Foundation 0x1ba2e4198 -[NSRunLoop(NSRunLoop) run] + 88
7 libxpc.dylib 0x1b9bc7178 _xpc_objc_main + 304
8 libxpc.dylib 0x1b9bc9acc xpc_main + 148
9 Foundation 0x1ba2e62c8 +[NSXPCListener serviceListener] + 170
10 PlugInKit 0x1c728ebb0 __PLUGINKIT_CALLING_OUT_TO_CLIENT_SUBSYSTEM_FOR_BEGINUSING__ + 31876
11 PlugInKit 0x1c728e8bc __PLUGINKIT_CALLING_OUT_TO_CLIENT_SUBSYSTEM_FOR_BEGINUSING__ + 31120
12 PlugInKit 0x1c728efc0 __PLUGINKIT_CALLING_OUT_TO_CLIENT_SUBSYSTEM_FOR_BEGINUSING__ + 32916
13 Foundation 0x1ba4c1004 NSExtensionMain + 64
14 libdyld.dylib 0x1b9df4360 start + 4Thread
0 libsystem_kernel.dylib 0x1b9deaa7c __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x1b9d0ebd4 _pthread_wqthread + 352
2 libsystem_pthread.dylib 0x1b9d11760 start_wqthread + 8com.google.firebase.crashlytics.MachExceptionServer
0 0x102f1f00c FIRCLSProcessRecordAllThreads + 392 (FIRCLSProcess.c:392)
1 0x102f1f3f0 FIRCLSProcessRecordAllThreads + 423 (FIRCLSProcess.c:423)
2 0x102f15c40 FIRCLSHandler + 34 (FIRCLSHandler.m:34)
3 0x102f185e8 FIRCLSMachExceptionServer + 524 (FIRCLSMachException.c:524)
4 libsystem_pthread.dylib 0x1b9d0dd8c _pthread_start + 156
5 libsystem_pthread.dylib 0x1b9d1176c thread_start + 8Thread
0 libsystem_kernel.dylib 0x1b9deaa7c __workq_kernreturn + 8
1 libsystem_pthread.dylib 0x1b9d0ebd4 _pthread_wqthread + 352
2 libsystem_pthread.dylib 0x1b9d11760 start_wqthread + 8com.apple.NSURLConnectionLoader
0 libsystem_kernel.dylib 0x1b9dc8634 mach_msg_trap + 8
1 libsystem_kernel.dylib 0x1b9dc7aa0 mach_msg + 72
2 CoreFoundation 0x1b9f70288 __CFRunLoopServiceMachPort + 216
3 CoreFoundation 0x1b9f6b3a8 __CFRunLoopRun + 1444
4 CoreFoundation 0x1b9f6aadc CFRunLoopRunSpecific + 464
5 CFNetwork 0x1bd2344e8 (Niepełna)
6 Foundation 0x1ba3db09c __NSThread__start__ + 848
7 libsystem_pthread.dylib 0x1b9d0dd8c _pthread_start + 156
8 libsystem_pthread.dylib 0x1b9d1176c thread_start + 8I haven't found much on the method that crashes the extension. Could it be Firebase component's fault or is there something I could investigate further?
Post not yet marked as solved
For the method:func startTunnel(options: [String: NSObject]? = nil, completionHandler: @escaping (Error?) -> Void)Docs say that the options dictionary should be nil whenever the tunnel is started via Connect On Demand. It turns out (iOS 12.2) that this is not true. I have following dictionary passed as an argument:[
"ServerAddress": /* */,
"match-hostname": /* */,
"AuthMethod": Password,
"VendorData": {
/* configuration */
},
"is-on-demand": 1
]Is docs or my configuration wrong?