vtkCommonInformationKeyManager Destruction Crash / Corrupt vfptr Table

I’m loading VTK as a visualization plugin from within an MFC application, and when I go to close my application and the plugin is unloaded with FreeLibrary, vtkCommonInformationKeyManager will crash. Immediately before the FreeLibrary call everything is fine, but when vtkCommonInformationKeyManager::ClassFinalize is called by the FreeLibrary call, all keys which weren’t created by vtkCommonCore are corrupt and crash with a read access violation exception when deleted. The key’s Name and Location parameter strings are still correctly set, but the __vfptr table is unreadable.

I realize that vtkCommonDataModel and vtkCommonExcecutionModel (among others) create their own information keys as static variables which are registered with the key manager which will properly delete them when VTK is closed. I’m wondering if these dlls are being unloaded first, and any memory they have allocated is being locked by Windows before the key manager tries to delete the keys? I have verified the destructors for the invalid keys are not being called.

If I manually override vtkCommonInformationKeyManagerCount so the first dll loaded will delete all referenced keys, they will unload cleanly, but if any of those static variables are referenced by a plugin which has not been disposed yet, I know it will be using a dangling pointer and would prefer not to leave loose ends. This test exposes that the same sort of issue also happens with vtkObjectFactory with the vtkObjectFactoryRegistryCleanupCounter, with similar results.

All of the references to VTK dlls are built into a static lib which is referenced by the plugin dll loaded by the exe. The static lib’s precompiled header includes a list of most of the vtk header files referenced alphabetically for build performance. The plugin dll has a list of #pragma comment(lib, “vtk….lib”) statements to link VTK into the plugin. I know the order of these libs is significant and possibly incorrect. The crash is not as bad if vtkCommonCore is the first item in the pragma list; no other position appears to have any effect. This list has been ordered according to the resolution order used when cmake compiles VTK from source, building a test project with the same modules and using that order, and alphabetically, all with no further effect.

Does anyone have any ideas to try and get VTK to properly clean up memory and close properly?

Is there a reason you’re trying to unload the library at all? Unloading libraries is fraught with issues. System callback registrations need undone, signal handlers need restored, vtkObserver stuff, etc. Nothing in VTK tracks that information at the library-lifetime level.

CommonCore and CommonDataModel have some nasty circular dependency going on with the InformationKeys; this may be the root cause of the issue, but the pragmatic fix is likely to just not unload the library (I tried untangling that cycle years ago and it didn’t go far; it’d need rewritten with some better OOP pattern than what it uses today).

In any case, you’re better off not unloading VTK at all (it’s not even valid to unload on macOS since unloading libraries which use thread-local storage is not possible there). Not that macOS is an issue with MFC stuff, but it’s completely untested on all platforms.

Cc: @RobertMaynard @brad.king

1 Like

VTK is only one part of a larger application, so it needs to fit within an IOC container plugin. Usually you would want to clean these plugins up when closing so you aren’t leaking memory/resources.

Getting VTK to actually clean this stuff up on library unload is going to take a larger effort. I suppose tracking down the immediate failure is the first thing to do, but I forsee this being a deep rabbit hole to actually get right.

If you’d like, getting the InformationKey stuff to use a more sensible OOP pattern than the intrusive things it’s doing today would be useful (the base class basically needs to know about all derived classes). Any suitable replacement would be fine; the test suite and exiting code should be testing InformationKey pretty comprehensively already.

Ok, Thanks. Experiments working with the plugin framework so VTK can be managed more by the operating system are a bit promising. It might deal with the immediate crash, but I expect that the best case will be looking more into these designs at some point.