|
FhSim
3.1.0
Marine systems simulation
|
| ID | 0204 |
| Class | BUG |
| Severity | 2 |
| Status | ready |
Models: —
Found: 2026-10-26 Windows round of feature/macos (MSVC 19.44, Debug, with visualization)
Ruling (owner, 2026-10-26): file now, fix later.
fmu-directional-derivative.FirstOrderStateFixture3.SerializedStateContinuesInASecondInstance reports [ OK ] and then the process ends with an access violation (ctest: Exception: SegFault). Once in about 60 Windows ctest logs. Reproduced with ctest -C Debug -R fmu-directional-derivative -j 16 --repeat until-fail:10, and under cdb (crash on run 50 of the case, while ctest loaded the machine):
libxml2 is linked statically into the engine DLL. A static libxml2 on Windows (LIBXML_STATIC without LIBXML_STATIC_FOR_DLL) frees the state of each thread that used it with a wait callback (RegisterWaitForSingleObject on the thread handle, USE_WAIT_DTOR), which runs on a thread-pool thread after the thread exits. When the last instance is released, FreeLibrary can unmap the DLL before or while that callback runs.
An FMU host on Windows can crash when it frees the last FhSim FMU instance. The run itself completes; the crash is in the teardown. Seen in the test only, which brings up a second instance in the same process.
DllMain frees a thread's state as the thread exits, so nothing runs after the unload. libxml2.dll then has to ship with the package, the playpen and every FMU (ResourceBundler, fhsim_conan, the FMU archive checks).GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_PIN) in FhsimDllBridge::Load: never unloaded, so the callback always finds its code. The DLL stays loaded until the process exits.ctest -C Debug -R fmu-directional-derivative -j 16 --repeat until-fail:50 on Windows without a failure.
A shared libxml2 changes what an FMU carries; a pinned DLL changes what a second load after CleanupXmlParser gets.