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

HaishinKit 2.0.x leaking #1651

Closed
drdaz opened this issue Dec 18, 2024 · 1 comment · Fixed by #1655
Closed

HaishinKit 2.0.x leaking #1651

drdaz opened this issue Dec 18, 2024 · 1 comment · Fixed by #1655
Milestone

Comments

@drdaz
Copy link

drdaz commented Dec 18, 2024

Describe the bug

Version 2.0.x is leaking its stack (or at least a significant portion of it).

To Reproduce

In the example app, in a debug session in Xcode:

Open the preferences tab
Tap Open Window
Close the window again
Repeat this a few times

Watch the process' unbounded memory growth in Xcode.

The example app leaks especially badly, with (I think) the whole stack including the view being leaked. I've attached a project which shows a more limited leak when doing a little manual teardown. Nonetheless, the library is still leaking heavily:

Screenshot 2024-12-18 at 15 03 42

To reproduce this in the attached project, debug it in Xcode, press the button on the first screen and go back a few times, and then Debug Memory Graph.

HaishinKitMemoryLeakTester.zip

Expected behavior

HaishinKit's objects should largely be deallocated when released.

Version

2.0.x

Smartphone info.

No response

Additional context

Likely cause

I've looked through your code, and I believe the cause of the issue is that you're capturing self when you initialize Tasks with a closure. The compiler doesn't warn about this, but Task {} behaves just like any other closure, and will capture self.

I suspect that extensive use of the [weak self] in ... guard let self else { ... } dance (or similar) will fix this.

A possibly related issue

While I've been working with this, I've seen what I believe to be a follow-on error from the above. After a certain number of initializations + attempted deinitializations, the newly initialized stack doesn't show any video in the preview.

If you look at the screenshot I attached under 'To Reproduce', you'll notice that a few of the objects have leaked n-1 times. This is the state of things after attempting to deallocate the stack after the video has failed to show. And it seems to consistently be the same objects at n-1.

I suspect this issue will disappear once the leaking stops, but I'm adding it here just in case this rings any bells 🙂

Screenshots

No response

Relevant log output

No response

@drdaz
Copy link
Author

drdaz commented Dec 19, 2024

After a certain number of initializations + attempted deinitializations, the newly initialized stack doesn't show any video in the preview.

So I've set a breakpoint at await startRunning() in MediaMixer / init() (iOS), and I've noticed that there's a very high correlation between this issue appearing, and self.videoIO.devices being empty. It's not 1:1, since on the first run this is empty, and seems to always work. But afterwards when execution stops at this breakpoint, if there are devices in the dictionary, the video displays. And if not, it doesn't.

So it looks like there's a potential timing issue here. But again, it's possible this is something that is caused by the leaking - it doesn't seem to ever happen on first run. I'm just making note of it here.

EDIT: I've found that by setting multiCamSessionEnabled: false at init, I don't see this issue (only using 1 cam at a time in the app).

The leaks remain though.

@shogo4405 shogo4405 added this to the 2.0.2 milestone Jan 1, 2025
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

Successfully merging a pull request may close this issue.

2 participants