Skip to content

0.26.1: selene_raylib can abort on shutdown due to double shader unload in cleanup_resources #18

@Milky2018

Description

@Milky2018

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:

  1. starts a 3D scene
  2. creates a few primitive meshes and lit materials
  3. creates a single spotlight
  4. takes a screenshot
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions