Hello!
We use `NWPathMonitor` within our SDK to read the network connection details. Recently, we discovered a crash which makes me considering the thread safety of `NWPath` struct. In following code, the program passed the line `12`, but crashed on line `13`:
import Network
@available(iOS 12, *)
extension NWPathMonitor {
var current: NetworkConnectionInfo {
let info = currentPath
return NetworkConnectionInfo(
reachability: NetworkConnectionInfo.Reachability(from: info.status),
availableInterfaces: Array(fromInterfaceTypes: info.availableInterfaces.map { $0.type }),
supportsIPv4: info.supportsIPv4, // <- passed
supportsIPv6: info.supportsIPv6, // <- crashed
isExpensive: info.isExpensive
)
}
}
To my best understanding, something did happen concurrently between the current thread advanced from line `12` to `13`. Thus, I consider thread safety issue around `NWPath` returned by the `currentPath`. What I can't understand however, is why this crashes at all, given that `NWPath` is a struct, so its immutable value captured on `let info` should be thread safe.
Crash details:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000020
VM Region Info: 0x20 is not in any region. Bytes before following region: 4369170400
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 00000001046c4000-0000000104ee8000 [ 8336K] r-x/r-x SM=COW ...g.app/Datadog
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [18544]
Thread 10 name: Dispatch queue: com.datadoghq.ios-sdk-logs-upload
Thread 10 Crashed:
0 libswiftCore.dylib 0x00000001ba2cf978 swift_unknownObjectRelease + 16
1 Datadog 0x0000000106508694 0x1064bc000 + 312980
2 Datadog 0x0000000106506e78 0x1064bc000 + 306808
3 Datadog 0x00000001065069b8 0x1064bc000 + 305592
4 Datadog 0x0000000106507618 0x1064bc000 + 308760
5 Datadog 0x00000001064cbfa8 0x1064bc000 + 65448
6 Datadog 0x00000001064d133c 0x1064bc000 + 86844
7 Datadog 0x00000001064d251c 0x1064bc000 + 91420
8 libdispatch.dylib 0x00000001ac41033c _dispatch_client_callout + 20
Note: we discovered this crash on iOS13.x device and couldn't manage to reproduce more times. In the crashing version of SDK, we do pass following `queue` to synchronize `NWPathMonitor` updates:
let queue = DispatchQueue(
label: "com.datadoghq.network-connection-info",
qos: .utility,
attributes: [],
target: DispatchQueue.global(qos: .utility)
)