Summary
On selene 0.26.1 / selene_raylib 0.26.1, shutting down a simple 3D app can abort inside cleanup_resources() with a double shader unload pattern.
I can reproduce this consistently with a minimal spotlight repro app.
Environment
Milky2018/selene = 0.26.1
Milky2018/selene_raylib = 0.26.1
- raylib backend from the published package
- macOS (Apple Silicon)
- raylib log reports:
Renderer: Apple M3 Max
Version: 4.1 Metal - 90.5
Repro
I made a minimal app that:
- starts a 3D scene
- creates a few primitive meshes and lit materials
- creates a single spotlight
- takes a screenshot
- calls
@system.exit()
The screenshot is saved successfully, but teardown aborts immediately after that.
Observed output
The important part is:
INFO: FILEIO: [/.../spotrepro_north_noshadow.png] Image exported successfully
INFO: SYSTEM: [/.../spotrepro_north_noshadow.png] Screenshot taken successfully
...
INFO: SHADER: [ID 6] Unloaded shader program data from VRAM (GPU)
INFO: SHADER: [ID 6] Unloaded shader program data from VRAM (GPU)
RUNTIME ERROR: abort() called
.../raylib/window.mbt:372 at @tonyfettes/raylib/internal/raylib.unload_shader
.../selene_raylib/src/top.mbt:2394 by @Milky2018/selene_raylib.cleanup_resources
.../selene_raylib/src/top.mbt:2460 by @Milky2018/selene_raylib.initialize
.../selene/src/system/app.mbt:453 by @Milky2018/selene/system.App::run
The key detail is that the same shader ID is reported as unloaded twice before the abort.
Likely root cause
This looks like a cleanup bug in selene_raylib:
cleanup_resources() unloads backend.lit_material, backend.lit_textured_material, and backend.shadow_material
- after that, it also explicitly unloads
backend.lighting_shader and backend.shadow_shader
From raylib itself, UnloadMaterial() already unloads the material shader when it is not the default shader:
void UnloadMaterial(Material material)
{
if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);
...
}
So if selene_raylib materials share the same custom shader, the current cleanup order appears to free that shader through UnloadMaterial() and then free it again through UnloadShader().
Relevant selene-raylib cleanup code:
selene_raylib/src/top.mbt:2381-2400
Relevant raylib implementation:
raylib/internal/raylib/rmodels.c:2215+
Why I think this is not app-specific
The crash happens after rendering is already complete and the screenshot has been written successfully. The failure is in backend teardown, not in scene logic.
Also, the duplicated shader unload log strongly suggests resource cleanup ownership is wrong in the backend.
Expected behavior
The app should shut down cleanly after @system.exit() without aborting.
Notes
I can provide the minimal repro package if needed, but the issue already seems actionable from the cleanup path and the duplicated shader unload.
Summary
On
selene 0.26.1/selene_raylib 0.26.1, shutting down a simple 3D app can abort insidecleanup_resources()with a double shader unload pattern.I can reproduce this consistently with a minimal spotlight repro app.
Environment
Milky2018/selene = 0.26.1Milky2018/selene_raylib = 0.26.1Renderer: Apple M3 MaxVersion: 4.1 Metal - 90.5Repro
I made a minimal app that:
@system.exit()The screenshot is saved successfully, but teardown aborts immediately after that.
Observed output
The important part is:
The key detail is that the same shader ID is reported as unloaded twice before the abort.
Likely root cause
This looks like a cleanup bug in
selene_raylib:cleanup_resources()unloadsbackend.lit_material,backend.lit_textured_material, andbackend.shadow_materialbackend.lighting_shaderandbackend.shadow_shaderFrom raylib itself,
UnloadMaterial()already unloads the material shader when it is not the default shader:So if
selene_raylibmaterials share the same custom shader, the current cleanup order appears to free that shader throughUnloadMaterial()and then free it again throughUnloadShader().Relevant selene-raylib cleanup code:
selene_raylib/src/top.mbt:2381-2400Relevant raylib implementation:
raylib/internal/raylib/rmodels.c:2215+Why I think this is not app-specific
The crash happens after rendering is already complete and the screenshot has been written successfully. The failure is in backend teardown, not in scene logic.
Also, the duplicated shader unload log strongly suggests resource cleanup ownership is wrong in the backend.
Expected behavior
The app should shut down cleanly after
@system.exit()without aborting.Notes
I can provide the minimal repro package if needed, but the issue already seems actionable from the cleanup path and the duplicated shader unload.