Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to avoid retain cycles when using OSCServer #56

Open
jcurtis-cc opened this issue Jan 28, 2021 · 15 comments
Open

How to avoid retain cycles when using OSCServer #56

jcurtis-cc opened this issue Jan 28, 2021 · 15 comments

Comments

@jcurtis-cc
Copy link

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?

@orchetect
Copy link
Member

orchetect commented Jan 28, 2021

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

@jcurtis-cc
Copy link
Author

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 :|

@orchetect
Copy link
Member

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

That was just the most obvious one I spotted.

@jcurtis-cc
Copy link
Author

jcurtis-cc commented Jan 28, 2021

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 :)

@devinroth
Copy link
Member

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

@devinroth
Copy link
Member

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
Copy link
Member

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

@devinroth
Copy link
Member

Wow. That was some bad programming.

@jcurtis-cc
Copy link
Author

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

@devinroth
Copy link
Member

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

@orchetect
Copy link
Member

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

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

@devinroth
Copy link
Member

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
Copy link
Member

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.

@jcurtis-cc
Copy link
Author

jcurtis-cc commented Jan 28, 2021 via email

@devinroth
Copy link
Member

Pretty much the entire OSCServer is completely different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants