Skip to content

Tests crash at exit (SIGSEGV) when VTK is built with VTK_DEBUG_LEAKS=ON #1278

Description

@hjmjohnson

Summary

When PlusLib is built against a VTK configured with VTK_DEBUG_LEAKS=ON, its test executables crash (SIGSEGV) at process exit, after the test logic has already completed successfully. Building against a VTK with VTK_DEBUG_LEAKS=OFF avoids the crash and the full test suite passes.

Symptom

A representative test (vtkPlusDeviceFactoryTest) prints its normal output including Test finished successfully!, then during static destruction:

Test finished successfully!
vtkDebugLeaks.cxx:236  WARN| Deleting unknown object: vtkPlusConfig
vtkDebugLeaks.cxx:236  WARN| Deleting unknown object: vtkObject
Segmentation fault: 11        (exit 139)

The crash is a wild jump to an unmapped address during vtkDebugLeaks's exit-time bookkeeping. It affects most tests that touch the vtkPlusConfig singleton (~16/32 in our runs), so the pass rate drops from 100% (release VTK) to ~28% (DEBUG_LEAKS=ON VTK).

Root cause (appears to be the same as #1070)

The Deleting unknown object warnings point at a leaked, orphaned vtkPlusConfig created by the circular singleton dependency documented in #1070:

vtkPlusConfig::GetInstance()new vtkPlusConfig() (before Instance is assigned) → the ctor calls vtkPlusLogger::Instance() → which re-enters vtkPlusConfig::GetInstance() (with Instance still NULL) → a second vtkPlusConfig is constructed, and one of the two is orphaned and leaked.

With DEBUG_LEAKS=ON, that leaked object (and a companion vtkObject, likely from the logger/timer singletons vtkPlusConfig's ctor instantiates) is still registered at process exit; when it is torn down after vtkDebugLeaks has finalized its table, the result is the unknown object warning followed by the segfault. DEBUG_LEAKS=OFF never runs that bookkeeping, so the same leak is silent.

The mitigation already in vtkPlusConfig::GetInstance() (creating the instance via vtkObjectFactory::CreateInstance("vtkPlusConfig") "to avoid Deleting unknown object") does not prevent it — the objects still show as unknown at teardown. Moving #include "vtkDebugLeaksManager.h" to be the first include (VTK's canonical requirement) also does not fix it, consistent with the real defect being the recursive GetInstance() rather than include ordering.

A real fix likely spans PlusLib + IGSIO

vtkPlusConfig's constructor instantiates vtkPlusLogger::Instance() and vtkIGSIOAccurateTimer::GetInstance() (which creates vtkIGSIOLogger), so a robust fix must break the recursion / order these singletons' destruction relative to vtkDebugLeaks across both projects. This matches the discussion in #1070 (circular dependency introduced in #493).

Workaround

Build the VTK that PlusLib links against with -DVTK_DEBUG_LEAKS=OFF (the default for release VTK, and what the PlusBuild superbuild uses). With that, the full suite passes.

Environment

  • PlusLib master
  • ITK 6 and ITK 5.4.6 (behaviour identical on both)
  • Static libraries (BUILD_SHARED_LIBS=OFF), macOS arm64, clang, VTK 9.6

Related: #1070 (the underlying vtkPlusConfig::GetInstance() memory leak).

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