CNA-BUG-253: SdlGpu_ConstructorExceptionSafety aborts with a double free, a defect CNA's own record calls real and leaves unfixed
Evidence basis: source-verified at the pinned commit; recorded by CNA's own run (not repeated here); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit c1c316b9; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
CNA's records say the classic SDL_GPU constructor-failure test aborts with 'double free detected in tcache 2'; every pass recorded since is a static-link build, and CNA diagnosed the same abort in an FNA3D test as a shared-library link-line defect.
- Identifier
CNA-BUG-253- Category
- Bug
- Subsystem
- Graphics & renderers
- Status
- Open
- Verified against
- CNA
c1c316b9(c1c316b9c7a846ce8002809c151fcd1af14942c9) - Severity
- Medium (a triage suggestion, not a project priority)
- Evidence basis
- Recorded by CNA: CNA's own recorded run, not repeated here
- Tests touching this area
- Yes: see Current tests
- Affected contract
- CNA::Internal::Renderers::SdlGpu::SdlGpuRenderer construction, under the transactional-construction contract REMED-GFX-028 states for it
Expected behaviour
The regression test's own header states the contract: “Every failed constructor must balance acquisition/release callbacks, leave no window-registry entry, preserve the caller-owned SDL_Window, and permit an immediately succeeding renderer”, with resource callbacks that make leaks and double-destruction observable. A double free on a failed construction violates it.
Actual behaviour at TARGET
The registered CTest SdlGpu_ConstructorExceptionSafety (target cna_test_sdlgpu_constructor_exception_safety, sdlgpu_constructor_exception_safety_test.cpp) aborts with free(): double free detected in tcache 2. CNA's plan record says the same binary 'built from the unmodified renderer sources (changes stashed, rebuilt from ccache) aborts identically - not introduced here, not investigated further', and its backlog calls it 'A real bug, not test debt', with an owner decision dated 2026-09-23 to fix it later as a small targeted bugfix. The latest record that runs the classic set on Linux, SMG-0043 (plan_sdlgpu_modern_graphics.md), still counts “the recorded constructor-exception double free” among its 26 failures. The record does not name the freeing site, so neither does this entry.
What the later records add: RRC-020 (plan_renderer_cleanup.md) records the test passing on the same private display in a static (CNA_SHARED_LIBRARY=OFF) multi-renderer tree, and CNA's macOS qualification (statically linked) records the whole SDL_GPU tree passing. On every non-Apple toolchain the test links CNA and, in addition, an explicit $<LINK_GROUP:RESCAN,…> of the static graphics archive cycle (the SDL_GPU examples' CMakeLists.txt); in a CNA_SHARED_LIBRARY=ON build, the Linux GCC and Clang default, CNA is libcna.so, and SharedRuntimeLibrary.cmake explains that archives on a consumer's link line beside libcna.so give a static object two copies. CNA's MSR-020 record (plan_samples_multirenderer.md) diagnosed exactly that as the exit-time double free of Fna3d_Device_Lifetime (two registrations of TouchPanel::gestures_' teardown) and removed the rescan from that test. Whether the SDL_GPU abort has the same cause is not recorded; by reading it is the likeliest one, which would make it a defect of the test's link line in shared-library builds rather than of the renderer. SDL_GPU is declared Supported (not Experimental) in GraphicsBackendMaturity.hpp.
Source locations
modules/renderers/sdl-gpu/examples/CMakeLists.txt— registers SdlGpu_ConstructorExceptionSafety; cna_sdlgpu_test links CNA, and on non-Apple toolchains the fixture adds a RESCAN link group of the static archive cyclemodules/renderers/sdl-gpu/examples/sdlgpu_constructor_exception_safety_test.cpp— the test and the transactional-construction contract in its headerplans/plan_sdlgpu_modern_graphics.md— the measured failure, the backlog entry that calls it a real bug, and SMG-0043's classic run that still counts itplans/plan_renderer_cleanup.md— RRC-020: the test passes in a static multi-renderer tree on the Linux private displayplans/plan_samples_multirenderer.md— MSR-020: the same exit-time double free diagnosed in Fna3d_Device_Lifetime as duplicated static archives beside libcna.socmake/SharedRuntimeLibrary.cmake— why archives on a consumer's link line beside libcna.so give a static object two copies
Evidence
Read at c1c316b9: the test registration, the test's header and CNA's plan record. Not executed: the abort is recorded by CNA, not reproduced for this entry, and the cause was not isolated (CNA's record says it was not investigated further). Found by the independent adversarial review of the graphics entries (a reviewer noticed it appeared only as a test name inside a cluster of failing classic SDL_GPU tests) and re-verified against the plan text by the orchestrator.
Independent re-verification: Read at c1c316b9: the test registration, the test source, the SdlGpuRenderer constructor transaction and CNA's plan records (SMG-0041/SMG-0042 backlog, PSG-0009, STREETS-0008, SDLGPU-56). Not executed: the abort is recorded by CNA, not reproduced for this entry, and the freeing site was not located by reading.
Re-verified at c1c316b9: read the test's link setup (cna_sdlgpu_test, cna_graphics_archive_cycle), SharedRuntimeLibrary.cmake and the records SMG-0043, RRC-020, MSR-020 and AM4-039/AM4-208; not executed. Every pass recorded since the abort is a static-link build; no record shows the test passing in a shared-library build.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
The test itself is the regression test and is registered; CNA's latest Linux run of the classic set (SMG-0043) still records it failing. CNA's earlier SDLGPU-56 result (2026-09-09) and its later static-link runs (RRC-020 on Linux, the macOS qualification) record it passing.
Regression test
The existing SdlGpu_ConstructorExceptionSafety, run in a CNA_SHARED_LIBRARY=ON tree (the configuration in which only failures are recorded) and kept in a lane that runs it under a double-free or leak-checking allocator.
Blast radius
If the abort is the link-line duplication described above, only this test executable is affected, in shared-library builds; if it is in the renderer, the classic SDL_GPU renderer (declared Supported in GraphicsBackendMaturity.hpp) on a construction that fails part-way. Which of the two it is has not been established.
Workaround
No workaround is known.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Verification: renderers
- Internals
- SDL_gpu renderer internals: tests
- Maintainer workflow
- Fix a renderer bug: triage
- Known issues
- Bug index