migueldeicaza / SwiftGodotKit

Embed Godot into Swift apps
229 stars 28 forks source link

PackedScene always seems to leak #25

Open pcbeard opened 9 months ago

pcbeard commented 9 months ago

In my bouncing ball simulator, I load my audio files like this:

@Godot
class Simulation: Node {
    var bouncesNode: Node?
    var bounces: [AudioStreamPlayer] = []

    func loadBounces() {
        #if false
        // This version loads the wav resources and creates the player nodes.
        // It does not leak any resources.
        let node = Node()
        bouncesNode = node
        for i in 0...5 {
            if let stream: AudioStream = GD.load(path: "res://bounce\(i).wav") {
                let bounce = AudioStreamPlayer()
                bounce.stream = stream
                stream.unreference()
                bounces.append(bounce)
                node.addChild(node: bounce)
            }
        }
        addChild(node: node)
        #else
        // This version instantiates the nodes from packed scene "res://bounces.tscn".
        if let bouncesScene: PackedScene = GD.load(path: "res://bounces.tscn") {
            if let node: Node = bouncesScene.instantiate() {
                bouncesNode = node
                addChild(node: node)
                self.bounces = node.getChildren().compactMap { $0 as? AudioStreamPlayer }
            }
            bouncesScene.unreference()
        }
        #endif
    }

    func stopBounces() {
        for bounce in bounces {
            if bounce.isPlaying() {
                bounce.stop()
            }
        }
        bounces.removeAll()
        if let bouncesNode {
            bouncesNode.queueFree()
            self.bouncesNode = nil
        }
    }
}

If I use the first code path, where I load the audio streams using GD.load() and create AudioStreamPlayer nodes, when my program terminates, there are no leaks resported. However, if I use the approach where I load a scene that contains the same nodes, I always see these resource leaks:

WARNING: ObjectDB instances leaked at exit (run with --verbose for details).
at: cleanup (core/object/object.cpp:2208)
WARNING: ObjectDB instances leaked at exit (run with --verbose for details).
     at: cleanup (core/object/object.cpp:2208)
Leaked instance: AudioStreamWAV:-9222522664122317664 - Resource path: res://bounce0.wav
Leaked instance: AudioStreamWAV:-9222519365587434334 - Resource path: res://bounce1.wav
Leaked instance: AudioStreamWAV:-9222516067052551004 - Resource path: res://bounce2.wav
Leaked instance: AudioStreamWAV:-9222512768517667674 - Resource path: res://bounce3.wav
Leaked instance: AudioStreamWAV:-9222509469982784344 - Resource path: res://bounce4.wav
Leaked instance: PackedScene:-9222505621692087127 - Resource path: res://bounces.tscn
Leaked instance: AudioStreamWAV:-9222506171447901014 - Resource path: res://bounce5.wav
Leaked instance: SceneState:-9222505071936273237
Leaked instance: AudioStreamPlaybackWAV:-9222318154959551312
Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).

This seems to indicate that the PackedScene is leaking. I've tried freeing it explicitly, but it doesn't seem to respond to the .free() message.

migueldeicaza commented 9 months ago

Could I get access to the source, so I don't need to setup a project to reproduce?

Or a minimal repro case?

pcbeard commented 9 months ago

Invited you to the project.