SwiftOSC icon indicating copy to clipboard operation
SwiftOSC copied to clipboard

How to avoid retain cycles when using OSCServer

Open jcurtis-cc opened this issue 4 years ago • 15 comments
trafficstars

Hi Devin,

Swift isn't my main language, I'm hoping you could make this clearer for me.

I'm instantiating an OSCServer inside a VC, which I only need while I'm inside that VC. I want to close that connection and deallocate the server when I leave the VC and return to the parent VC.

By making the server.delegate = self I cause a retain cycle even if I try setting server.delegate = nil in viewWilDisappear()

I've tried declaring my server as weak and unowned

What am I missing?

jcurtis-cc avatar Jan 28 '21 03:01 jcurtis-cc

In OSCServer.swift,

open class OSCServer {
    // ...

    open var delegate: OSCServerDelegate?

    // ...
}

delegate is holding a strong reference here.

open var delegate should be open weak var delegate

orchetect avatar Jan 28 '21 03:01 orchetect

Thanks for the speedy response @orchetect - I had this suspicion, nice to have that confirmed! I'm still getting a retain cycle after adding weak there. I can't understand what I'm doing wrong here :|

jcurtis-cc avatar Jan 28 '21 04:01 jcurtis-cc

There could still be retain cycles elsewhere in SwiftOSC or in your code.

That was just the most obvious one I spotted.

orchetect avatar Jan 28 '21 04:01 orchetect

Thanks @orchetect - think i've tried every variation of weak and unowned in every reference to the delegate I can. Removing the instantiation of the OSCServer in this view controller stops the memory leak. I can't figure out how to deallocate it. The VC is deiniting but the OSCServer stays allocated even when setting it to nil - so every time the VC is pushed, a new OSCServer ends up on the stack

As a workaround I'm instantiating the OSCServer at the top level in appDelegate like one of Devin's examples and setting that VC to the delegate (using self). I can't deallocate it but I can stop it and start it. I'm working on an app that's sensitive to memory so I'm hoping for a fix!

I'm sure this is something very obvious to Devin that I just can't see :)

jcurtis-cc avatar Jan 28 '21 06:01 jcurtis-cc

Don't rule out the possibility that I screwed up somewhere.

devinroth avatar Jan 28 '21 06:01 devinroth

In OSCServer.swift line 44.

    func run() {
        DispatchQueue.global().async{
            while true {
                let (data,_,_) = self.server.recv(9216)
                if let data = data {
                    if self.running {
                        let data = Data(data)
                        self.decodePacket(data)
                    }
                }
            }
        }
    }

Probably shouldn't be while true. Try changing that to while self.running. Then open func start() needs to have run() in it .Or something like that.

devinroth avatar Jan 28 '21 07:01 devinroth

I don't have time to dig into this right now.

devinroth avatar Jan 28 '21 07:01 devinroth

Wow. That was some bad programming.

devinroth avatar Jan 28 '21 07:01 devinroth

Awesome, thanks for the quick response Devin - I'll test this and make a PR if it works

jcurtis-cc avatar Jan 28 '21 07:01 jcurtis-cc

It might not completely solve the issue. But there are definitely issues with that block.

devinroth avatar Jan 28 '21 07:01 devinroth

Also be aware that async { } closure is holding a strong reference to self.

I'd start by adding [weak self] to the closure.

orchetect avatar Jan 28 '21 07:01 orchetect

Maybe I should just pitch @orchetect 's OSC library. https://github.com/orchetect/OSCKit

He doesn't include the network layer so it's not plug and play but if you're good with that stuff it should be pretty easy. I know he's done some pretty extensive testing and uses it daily.

devinroth avatar Jan 28 '21 07:01 devinroth

Also, If you check out the dev branch, I was working on using a different Swift Network framework. Maybe try giving that a spin. Full disclosure it's been a while and I'm not sure how well it works.

devinroth avatar Jan 28 '21 07:01 devinroth

Cheers, had a quick look - couldn’t see exactly where the network framework changed, i’ll keep an eye on the dev branch if you become active on there again :)

On 28 Jan 2021, at 18:37, Devin Roth [email protected] wrote:

 Also, If you check out the dev branch, I was working on using a different Swift Network framework. Maybe try giving that a spin. Full disclosure it's been a while and I'm not sure how well it works.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

jcurtis-cc avatar Jan 28 '21 08:01 jcurtis-cc

Pretty much the entire OSCServer is completely different.

devinroth avatar Jan 28 '21 09:01 devinroth