Background URLSession http/3 URLSessionUploadTask not started in real device

I'm trying to upload large files in a background URLSession to a server that accepts HTTP/3 requests. Per its design, the server uses a self-signed SSL certificate.

In my testing, I can create a regular URLSession (foreground) with the following:

        var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0)

        request.assumesHTTP3Capable = true

        request.httpMethod = "POST"

       self.session.dataTask(with: request) {
<snip>
}

And handles the SSL certificate challenge by implementing the following for the delegate:

  func urlSession(
        _ session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping @Sendable (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
    ) 

This approach works and I can communicate with the server. But when I try to apply the same for a background session for an upload task, the task seems to be stuck, i.e. never started by the system.

More specifically, the background session upload task works with iOS simulator. But on a real device connected to macOS, the task never started, and none of the delegate methods are called. The http/3 server didn't receive any request either.

The background session was created:

        let appBundleName = Bundle.main.bundleURL.lastPathComponent.lowercased().replacingOccurrences(of: " ", with: ".")
        let sessionIdentifier: String = "com.networking.\(appBundleName)"
        let config = URLSessionConfiguration.background(withIdentifier: sessionIdentifier)
        self.session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

later, an upload task was created :

        var request = URLRequest(url: dst, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 6.0)
        request.assumesHTTP3Capable = true
        request.httpMethod = "POST"

        let backgroundTask = self.session.uploadTask(with: request, fromFile: src)
        backgroundTask.resume()

My question(s): why is the background session upload task stuck? Is there a way to find out where it is stuck?

Does a background URLSession support app's delegate handling SSL certificate challenge?

The test env:

Xcode 14.2

macOS 12.6.7

iOS 15.7.7

Thanks!

Adding more info here as it's over the limit of a comment.

I used WireShark to capture the packets from the real device. Looks like when the upload task is in a foreground URLSession, the session establishes http/3 QUIC connection without trying / waiting Http/1.1 first. This is expected as I am using assumesHTTP3Capable = true. But in a background URLSession, looks like the system tries to talk to Http/1.1 first, and as the server only talks http/3, the task fails to start. Is this behavior expected? If yes, why the difference between a foreground session and a background session?

It is some time ago when I did connect using self-signed certificate to a server. At that time, I had to provide an App transport security exception in the app signing and capabilities section. There I needed to list the exception domains, addresses where the app connects to with unsigned certs.

Maybe this is needed in your case?

For those reading along at home, I’ll be helping keepsimple in a different context.

Share and Enjoy

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

Is there any chance for such bugs get fixed in iOS 15 future releases?

I’d rate that as very unlikely. Historically we only update old iOS release to fix security bugs.

Share and Enjoy

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

Background URLSession http/3 URLSessionUploadTask not started in real device
 
 
Q