|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0023 |
| Class | API |
| Severity | 2 |
| Status | ready |
| Models | — |
| Found | 2026-09-25, filed from fhsim_fishery FISH-0041 on the owner's decision |
| Decision needed | — (Karl-Johan Reite decided 2026-09-25 to file this as ready: add the hook) |
The visualisation part of the SimObject interface is two pure virtuals and nothing else (include/fhsim/simobject/SimObjectInclude.h:305-321):
IModelVisualizationHooks (src/engine/model/IModelVisualizationHooks.h:31-54) mirrors this: RenderInit and RenderUpdate, no release. ModelStructure::RenderInit (src/engine/model/ModelStructure.cpp:221-233) forwards to every SimObject.
At the end of a visualised run VisualizationObserver::OnSimulationEnd (src/visual/observer/VisualizationObserver.cpp:70-73) calls FhVisualization::Shutdown (src/visual/renderer/FhVisualization.cpp:291-355), which destroys the scene manager (:342) and, when it owns it, deletes the Ogre root (:351-352). The SimObjects are destroyed later, with the model. So the only place a SimObject can release the scene nodes, entities and manual objects it created in RenderInit is its destructor, and by then the scene manager it cached is freed memory.
Downstream this has already crashed twice and is now guarded case by case:
Auv::~Auv segfaulted FhVis on exit. Auv (src/auv/Auv.cpp:30-51, used at :277) and SensorEchosounder (src/auv/SensorEchosounder.cpp:60-81, used at :250) now release only when SceneIsStillAlive(m_sceneMgr), i.e. Ogre still has the "main" scene manager. fhsim_fishery AGENTS.md makes that guard a house rule until this hook exists.1507a3f and 5bf8d11): visual::ScalarPlane, ScalarVolume and FlowPlane segfaulted at shutdown in Release(); each now returns early when !OgreRootIsAlive() (src/environment/visual/OgreLifetime.h:29, used in ScalarVolume.cpp:112, ScalarPlane.cpp:59, FlowPlane.cpp:108).Every visualised library must know that the Ogre root dies before its SimObjects and guard each destructor; one that does not segfaults every visualised run at shutdown. With the guard, geometry is never released by its owner at all, only swept up with the scene. The rule is not visible in the interface.
Add to SimObject in SimObjectInclude.h, under FH_VISUALIZATION, next to RenderUpdate:
Empty default, not pure, so no existing SimObject has to change.
RenderRelease() to IModelVisualizationHooks, implement it in ModelStructure by calling RenderRelease() on every SimObject (reverse creation order), and add an empty override to SimObjectIterator if it needs one.m_renderHooks->RenderRelease() in VisualizationObserver::OnSimulationEnd and VisualizationSDLObserver::OnSimulationEnd (and any other path that reaches FhVisualization::Shutdown, including its destructor and the FMU teardown) before m_visualization.Shutdown(), only when RenderInit ran.Follow-ups in other repositories, once this is released:
Auv::~Auv and SensorEchosounder::~SensorEchosounder into RenderRelease() overrides, and drop the SceneIsStillAlive guards and the AGENTS.md house rule (FISH-0041).ScalarVolume::Release(), ScalarPlane and FlowPlane release from RenderRelease(); the OgreRootIsAlive() guards from ENV-0023 can then stay as a safety net or go.A visualisation-build test with a stub SimObject that records RenderInit, RenderRelease and its destructor, run through ModelStructure and a visualisation observer (headless if available): RenderRelease is called exactly once, after the last RenderUpdate, while Ogre::Root::getSingletonPtr() is non-null and hasSceneManager("main") is true, and before the destructor. A second case with a SimObject that does not override it shows the default is harmless.
Low for existing code: the default is empty. The ordering must hold on every shutdown path (window closed, user stop, FMU terminate, exception unwinding); a path that skips the call just falls back to today's behaviour, which is why downstream guards may stay until each path is covered. An FMU that reuses an existing Ogre root (m_rootOwned == false, FhVisualization.cpp:141-144) must still get the call, since the scene manager is destroyed there too.