A server with the specified hostname could not be found exception

Hi, I have been working on the app that implements DNS Proxy Extension for a while now, and after a couple builds to TestFlight I noticed that I got a couple crashes that seem to be triggered by EXC_BREAKPOINT (SIGTRAP)

After some investigation, it was found that crashes are connected to CFNetwork framework. So, I decided to additionally look into memory issues, but I found the app has no obvious memory leaks, no memory regression (within recommended 25%, actual value is at 20% as of right now), but the app still uses 11mb of memory footprint and most of it (6.5 mb is Swift metadata).

At this point, not sure what's triggering those crashes, but I noticed that sometimes app will return message like this to the console (this example is for PostHog api that I use in the app):

Task <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1> finished with error [18 446 744 073 709 550 613] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=8, NSUnderlyingError=0x1072df0f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, _NSURLErrorNWResolutionReportKey=Resolved 0 endpoints in 2ms using unknown from cache, _NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalUploadTask <0ABDCF4A-9653-4583-9150-EC11D852CA9E>.<1>"
), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://us.i.posthog.com/batch, NSErrorFailingURLKey=https://us.i.posthog.com/batch, _kCFStreamErrorDomainKey=12}

If DNS Proxy Provider uses custom DoH server for resolving packets, could the cache policy for URLSession be a reason?

I had a couple other ideas (HTTP3 failure, CFNetwork core issues like described here) but not sure if they are valid

Would be grateful if someone could give me a hint of what I should look at

Answered by DTS Engineer in 806531022
In my case, Filter Control Provider writes data received from MDM configuration profile, then Filter Data Provider reads this data to use it for flow filtering.

OK. That should be possible by putting the data into an app group. The control provider will have read/write access to that app group; the data provider will only be able to read it.

And, yes, you will need some sort of concurrency control there (-:

But my Filter Data Provider also writes some data about intercepted flow, that is later used for resolving them.

As long as this only needs to be read back by the data provider, you’re all good. Just put the data into the data provider’s container.

You still might need concurrency control though, although it’s only intra-process concurrency control. That is, multiple threads within the data provider might be accessing this data and you have to make sure they don’t stomp on each other.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for your response!

It only happens during the first build or if a new build is initiated from Xcode on top of existing configuration (app was previously installed)

But after some investigation, I found that packet hex is slightly different from system resolver's response. But even then the issue occurs only during first build and is fixed by reconnecting to the network

And if this occurs, then no URLSession completes successfully, unless network connection is toggled, then it works fine again

I found that packet hex is slightly different from system resolver's response

Regarding this, would it make more sense to receive already serialised packet from DoH by using dns-message content type? Because as of right now all de/se-rialization is handled in the DNS Proxy Provider

would it make more sense to receive already serialised packet from DoH by using dns-message content type?

I don’t think that the system has a preference here; it’s basically an implementation detail of your provider.

However, to me it definitely makes more sense, in that it avoids you having to write extra code (well, I guess the code is already written, but you could remove it).

It only happens during the first build or if a new build is initiated from Xcode on top of existing configuration (app was previously installed)

Well, that’s strange.

Does this only happen when you’re debugging with Xcode? Or do you see it during deployment? For example, if you replace an older TestFlight build with a newer one?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Does this only happen when you’re debugging with Xcode? Or do you see it during deployment? For example, if you replace an older TestFlight build with a newer one?

It normally doesn't happen during debugging with Xcode. As for deployment, yes, when user first installs the app on their device, it returns this exception, but Wi-Fi toggle fixes it

It's not confirmed yet, but I think avoiding in-app packet serialisation might fix the problem. From what I had before, I noticed that some fields in DNS packet were encoded using UInt8 or Bool but Opcode and RCode should be UInt4 and Z is normally UInt3, etc.

But after sending packet back directly from DoH, I don't see any mismatch in packet structure

I will be able to verify if that resolved the issue soon after testing new build

It's been a while, but I wanted to give a quick update for anyone who might encounter a similar issue.

In my case, the problem had two parts:

  1. Parsing DNS Packets in a Custom DNS Proxy Provider

    If you're using a custom DoH resolver in your DNS Proxy Provider, it's important to parse the entire DNS packet, not just the requested domain. I recommend using the wire format with the application/dns-message MIME type and sending the complete packet to your provider for resolution.

  2. Managing NWConnection Lifecycles

    When using NWConnection for handling connections with local or remote resolvers, ensure proper lifecycle management for each instance of NWConnection. Use stateUpdateHandler to monitor the connection's state and release connections appropriately after they are completed.

    A common issues is forgetting to release resources for completed connections, leading to memory leaks that can be a bit hard to detect. Some resources suggest setting stateUpdateHandler = nil and then calling .cancel() on the connection. However, simply calling .cancel() is quite enough, as it automatically releases all associated blocks and handlers.

Here's a snippet from the documentation to clarify:


/// Cancel the connection and release all associated handlers.
/// 
/// Cancel is asynchronous. The last callback will be to the `stateUpdateHandler` with the `.cancelled` state.
/// After that, all handlers are released to break retain cycles.
/// Subsequent calls to `cancel()` are ignored.
final public func cancel()

In my case, these two relatively small issues were causing significant and inconsistent issues within the app.

Thanks to Quinn for all the help!

A server with the specified hostname could not be found exception
 
 
Q