URLSessionWebSocketTask memory leak bug

memory leak in when working with URLSession webSocketTask

introductory command line app, mac os Ventura 13.2.1

the first leak is fixed on the URLSessionWebSocketDelegate delegate func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?)

further when calling receive closures or through func receive() async throws -> URLSessionWebSocketTask.Message

the system is constantly leaking memory

In order to understand how sad everything is, I recommend opening 20-50 sockets in parallel for large data streams, as an example, financial exchanges

per day of work, 0.2-1 gigabytes of leakage will accumulate

there is one suggestion, maybe it will help fix the bug, it is connected with another leak in the system that appears in the absence of user interactions,

example if we create 20-50 swiftUI labels and start updating them fast enough 5-10 times per second and stop interacting with the mouse, keyboard and touchbar, we will get a memory leak when the old label data is not destroyed by the system - and without touching the keyboard, the mouse in an hour several gigabytes will leak us, then if you move the mouse or press a button on the keyboard, the system will clear the memory

URLSessionWebSocketTask memory leak bug

It sounds like you’re trying to report a bug. If so, please use Feedback Assistant for that. See my Bug Reporting: How and Why? post for hints and tips on that front.

Please post your bug number, just for the record.

Share and Enjoy

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

I have noticed a strange behaviour as wee, as follows: I have a basic app, nothing in it. Just calls an empty view controller. This is all there is:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        guard let windowScene = (scene as? UIWindowScene) else { return }
        window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        let viewController = ViewController()
        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()

 
        let myDelegate = ZZZWebSocketDelegate()
        let sessionConfiguration = URLSessionConfiguration.default
        let urlSession = URLSession(configuration: sessionConfiguration, delegate: myDelegate, delegateQueue: OperationQueue())
        sessionConfiguration.timeoutIntervalForRequest = 10
        sessionConfiguration.timeoutIntervalForResource = 10
        sessionConfiguration.allowsCellularAccess = true
        sessionConfiguration.waitsForConnectivity = true
    }

The anomaly comes from the delegate for URLSession (ZZZWebSocketDelegate), which contains nothing at the moment:

public class ZZZWebSocketDelegate: NSObject, URLSessionWebSocketDelegate {

    open func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didOpenWithProtocol protocol: String?) {
    
         print("Opened")
    }

    open func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask, didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
     
         print("Closed")
    }
}

I run the app and there are memory leaks:    

     Also profiling the app withIinstruments shows a leak.

Anybody have any idea as to why this is?

    

I solved the problem by calling invalidateAndCancel() method of URLSession created when WebSocket closed.

I solved the problem by calling invalidateAndCancel() method of URLSession created when WebSocket closed.

Our advice is that you use Network framework for WebSocket. See TN3151 Choosing the right networking API. This is a classic example of why we recommend that [1]. WebSocket is effectively a connection, which maps well to NWConnection. URLSession is designed for running HTTP requests, and in that context it makes sense to group your requests in a session, and those sessions are intended to be long-lived, and you must explicitly invalidate them otherwise.

Share and Enjoy

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

[1] If you’re curious about the other reasons, see this thread.

URLSessionWebSocketTask memory leak bug
 
 
Q