godotengine / godotengine/godot

C# ResourceLoader cache may end up holding onto disposed objects

Open
#87,545 4 comments 1 reaction 0 assignees View on GitHub
needs testing topic:dotnet
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

- Godot 4.2.1 Stable mono

### System information

Godot v4.2.1.stable.mono - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2080 Ti (NVIDIA; 31.0.15.4633) - Intel(R) Core(TM) i9-9900 CPU @ 3.10GHz (16 Threads)

### Issue description

In my project I support mods, the editor is also built into the game itself. So after exiting the editor I trigger a full reload of my mods. This involves first disposing of all textures, fonts, shaders, etc...

Then I reload them, sometimes (not always) randomly it seems the ResourceLoader ends up hanging onto the disposed C# wrapper. From this point on the cache will be broken and every reload will just give you the disposed wrapper.

Also using ResourceLoader.CacheMode.Replace does not fix this issue, from this point you need to use ResourceLoader.CacheMode.Ignore to get the texture.

A solution here would be to check if the object has been disposed before giving it back to the user on ResourceLoader.Load.

### Steps to reproduce

1. Load a bunch of textures
2. Use the textures in Sprite2D or TextureRects
3. Free the sprites and TextureRects
4. Call .Dispose() on said textures
5. Repeat until resource loader starts serving back a disposed wrapper.

### Minimal reproduction project (MRP)

Here is an image showing what i mean, see below for a reproduction project.
![image](https://github.com/godotengine/godot/assets/35214615/438454fe-6689-4487-99d2-71259866c0e0)

Managed to reproduce
[TextureDisposeIssue.zip](https://github.com/godotengine/godot/files/14050987/TextureDisposeIssue.zip)

Contributor guide

Open the contributing guide

Research direction

Start at ResourceLoader.Load and its cache handling, focusing on how C# wrappers are returned after Dispose() and how CacheMode.Replace behaves. Use the linked TextureDisposeIssue.zip reproduction and repeat the listed load, free, dispose, and reload steps. Done means reloads no longer return a disposed wrapper and the reported cache behavior is covered by a reproducible verification.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, godot
Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.