STYLE: Replace non-POD ctkLogger globals with Q_GLOBAL_STATIC_WITH_ARGS#1409
STYLE: Replace non-POD ctkLogger globals with Q_GLOBAL_STATIC_WITH_ARGS#1409hjmjohnson wants to merge 2 commits intocommontk:masterfrom
Conversation
ef1fe38 to
f074096
Compare
b460980 to
89eca08
Compare
89eca08 to
429d94d
Compare
429d94d to
9cd24a9
Compare
|
|
2 similar comments
|
|
|
|
CTK Validation Report for PR #1409Date: 2026-04-03T16:27:30Z
Validation Actions Performed
CTK-in-Slicer Build Detail (classified warnings)
Slicer Test Detail (classified failures)
CTK Test Failures (proposed
|
| Test | Status | Related PR/Issue |
|---|---|---|
ctkFontButtonTest |
🔄 Timeout | #1395 — WIP: Fix ctkFontButtonTest hang and disable stale modal dialog tests |
ctkLanguageComboBoxTest |
🔄 Failed | #1400 — BUG: Fix ctkLanguageComboBox locale normalization and selection |
ctkWidgetsUtilsTestGrabWidget |
🖥️ Failed | — — Requires OpenGL display — fails in headless environments |
ctkColorPickerButtonEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkDirectoryButtonEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkFileDialogEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkMenuComboBoxEventTranslatorPlayerTest1 |
🔄 Failed | #1395 — Modal dialog event translator failure |
vtkLightBoxRendererManagerTest1 |
🖥️ SEGFAULT | — — GPU/GLSL infrastructure — SEGFAULT in headless environments |
ctkVTKMagnifyViewTest2OddOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2OddEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKTextPropertyWidgetEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
Qt6 (10 failures):
| Test | Status | Related PR/Issue |
|---|---|---|
CTKPluginFrameworkAppTests |
🐛 Subprocess aborted | — — Qt6 subprocess abort — pre-existing |
ctkLanguageComboBoxTest |
🔄 Failed | #1400 — BUG: Fix ctkLanguageComboBox locale normalization and selection |
ctkWidgetsUtilsTestGrabWidget |
🖥️ Failed | — — Requires OpenGL display — fails in headless environments |
ctkWorkflowWidgetTest1 |
🐛 Failed | — — Qt6 QStateMachine async transitions — widgets not visible in time |
ctkWorkflowWidgetTest2 |
🐛 Failed | — — Qt6 QStateMachine async transitions — widgets not visible in time |
vtkLightBoxRendererManagerTest1 |
🖥️ SEGFAULT | — — GPU/GLSL infrastructure — SEGFAULT in headless environments |
ctkVTKMagnifyViewTest2OddOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2OddEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
CTK Test Failures (reference 935c4e04)
Qt5 (25 failures):
| Test | Status | Related PR/Issue |
|---|---|---|
ctkBackTraceTest |
🐛 Failed | — — Fixed on master — symbol resolution on Linux with hidden visibility |
ctkLoggerTest1 |
🐛 Failed | — — Fixed on master — default log level expectation |
ctkFontButtonTest |
🔄 Timeout | #1395 — WIP: Fix ctkFontButtonTest hang and disable stale modal dialog tests |
ctkLanguageComboBoxTest |
🔄 Failed | #1400 — BUG: Fix ctkLanguageComboBox locale normalization and selection |
ctkMessageBoxDontShowAgainTest |
🐛 Failed | — — Fixed on master — ButtonRole vs StandardButton |
ctkWidgetsUtilsTestGrabWidget |
🖥️ Failed | — — Requires OpenGL display — fails in headless environments |
ctkColorPickerButtonEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkDirectoryButtonEventTranslatorPlayerTest1 |
🔄 Failed | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkFileDialogEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
ctkMenuComboBoxEventTranslatorPlayerTest1 |
🔄 Failed | #1395 — Modal dialog event translator failure |
ctkPathLineEditEventTranslatorPlayerTest1 |
🐛 Failed | — — Fixed on master — XML widget name update |
ctkDICOMPatientDelegateTest1 |
🐛 Failed | — — Fixed on master — default header height |
vtkLightBoxRendererManagerTest1 |
🖥️ SEGFAULT | — — GPU/GLSL infrastructure — SEGFAULT in headless environments |
ctkVTKErrorLogModelFileLoggingTest1 |
🐛 Failed | — — Fixed on master — Qt6 + line stability |
ctkVTKHistogramTest3 |
🐛 Failed | — — Fixed on master — out-of-bounds read with signed VTK_CHAR |
ctkVTKPropertyWidgetTest |
🐛 Failed | — — Fixed on master — float precision comparison |
ctkVTKThresholdWidgetTest1 |
🐛 Failed | — — Fixed on master — threshold lost after setRange |
ctkVTKSurfaceMaterialPropertyWidgetTest1 |
🐛 Failed | — — Fixed on master — opacity comparison |
ctkVTKMagnifyViewTest2OddOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2OddEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKRenderViewEventTranslatorPlayerTest1 |
🐛 Failed | — — Fixed on master — Qt6 protected operator= |
ctkVTKScalarBarWidgetEventTranslatorPlayerTest1 |
🐛 Failed | — — Fixed on master — missing XML events |
ctkVTKTextPropertyWidgetEventTranslatorPlayerTest1 |
🔄 Timeout | #1395 — Modal dialog timeout — addressed in test fix PR |
Qt6 (10 failures):
| Test | Status | Related PR/Issue |
|---|---|---|
CTKPluginFrameworkAppTests |
🐛 Subprocess aborted | — — Qt6 subprocess abort — pre-existing |
ctkLanguageComboBoxTest |
🔄 Failed | #1400 — BUG: Fix ctkLanguageComboBox locale normalization and selection |
ctkWidgetsUtilsTestGrabWidget |
🖥️ Failed | — — Requires OpenGL display — fails in headless environments |
ctkWorkflowWidgetTest1 |
🐛 Failed | — — Qt6 QStateMachine async transitions — widgets not visible in time |
ctkWorkflowWidgetTest2 |
🐛 Failed | — — Qt6 QStateMachine async transitions — widgets not visible in time |
vtkLightBoxRendererManagerTest1 |
🖥️ SEGFAULT | — — GPU/GLSL infrastructure — SEGFAULT in headless environments |
ctkVTKMagnifyViewTest2OddOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2OddEven |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
ctkVTKMagnifyViewTest2EvenOdd |
🖥️ Failed | — — VTK OpenGL render — fails without GPU |
🔄 = addressed in open PR | 🖥️ = infrastructure/display dependent | 🐛 = known bug | ➖ = wontfix
Generated by /validate-ctk-pr skill | cache: /home/johnsonhj/src/CTK/.claude/validate-cache
Static ctkLogger variables have non-trivial constructors (they register with the logging framework) and non-trivial destructors, making them non-POD global statics and triggering clazy:non-pod-global-static. Q_GLOBAL_STATIC_WITH_ARGS wraps the object in a function-local static: initialization is deferred to first use (lazy), thread-safe via a once-guard, and destruction occurs in well-defined reverse order at exit, eliminating the Static Initialization Order Fiasco risk. Because Q_GLOBAL_STATIC returns a pointer-like proxy rather than a reference, all logger.method() call sites are updated to logger->method(). Files in Libs/Core, Libs/DICOM/Core, Libs/DICOM/Widgets, Libs/Visualization/VTK/Core, Libs/Visualization/VTK/Widgets, and Libs/Widgets require an additional #include <QGlobalStatic> where that header is not already transitively available. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ctkCorePythonQtDecorators.h and ctkDICOMCorePythonQtDecorators.h each declared 'static ctkLogger logger(...)' at file scope, triggering the clazy:non-pod-global-static warning. Although these are public headers, the logger variable has internal linkage and is not part of any exported class interface. Replace with Q_GLOBAL_STATIC_WITH_ARGS for SIOF-safe lazy initialization. Each translation unit that includes the header still gets its own logger instance (Q_GLOBAL_STATIC uses an anonymous namespace internally), so behavior is unchanged. All logger.method() call sites in both headers are updated to logger->method(). Note: downstream code directly referencing 'logger' by name after including these headers (unlikely in practice) would need the same .method() -> ->method() update. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9cd24a9 to
c159090
Compare
|
@jamesobutler I created a script to build against qt5, qt6, and Slicer qt5 and this pr does not introduce any new warnings, errors, or regressions. It does fix some previous issues, and it improves the clazy static analysis. Let me know if there is something I can do to keep the CTK updates moving forward. |
Summary
Fixes
clazy:non-pod-global-staticwarnings on file-scopectkLoggerglobals by converting them toQ_GLOBAL_STATIC_WITH_ARGS.This is one of two PRs split from a combined approach (the companion PR #1410 handles string constants via
constexpr QLatin1String).Problem
static ctkLogger logger("name")at file scope has a non-trivial constructor and destructor (it connects to the logging framework at startup), triggering thenon-pod-global-staticclazy warning. This is a real SIOF risk: if another file-scope static calls the logger during its own initialization, the logger may not be constructed yet.Approach
Q_GLOBAL_STATIC_WITH_ARGSis a Qt macro that wraps the object in a function-local static with a thread-safe once-guard. The object is constructed lazily on first access and destroyed in reverse order at shutdown — SIOF-safe.The macro returns a pointer-like proxy, so all
logger.method()call sites becomelogger->method().Public Header Notice
Two public headers were also updated:
Libs/Core/ctkCorePythonQtDecorators.hLibs/DICOM/Core/ctkDICOMCorePythonQtDecorators.hThese headers each declared
static ctkLogger logger(...)at file scope, visible to any translation unit that includes them. Althoughloggerhas internal linkage (per-TU, not exported), the type changes fromctkLoggerto theQGlobalStatic<ctkLogger>proxy.Impact on downstream code: Any external code that directly referenced
loggerby name after including these headers (vialogger.method()) would need to update tologger->method(). In practice this is extremely unlikely —loggeris an internal implementation detail of the decorator methods defined in these headers, not part of any public class interface.Note:
Q_GLOBAL_STATIC_WITH_ARGSin a header gives each including TU its own instance (Qt wraps the declaration in an anonymous namespace), preserving the same per-TU isolation as the originalstatic.Comparison with PR #1398
Q_GLOBAL_STATIC_WITH_ARGSconstexpr QLatin1String(PR #1410)Files Changed
59 files across:
Libs/DICOM/Core/— ctkDICOMDatabase, ctkDICOMIndexer, all DICOM job/worker files,ctkDICOMCorePythonQtDecorators.hLibs/DICOM/Widgets/— 9 widget filesLibs/Core/ctkJobScheduler.cpp,ctkCorePythonQtDecorators.hLibs/Widgets/— 4 widget filesLibs/Visualization/VTK/Core/andWidgets/— 8 filesTesting
Built successfully against Qt5 (
cmake-build-clazy-qt5, Apple clang) and Qt6 (cmake-build-clazy-qt6) on macOS ARM64.Part of the fix for #1407. See also companion PR #1410 for
constexpr QLatin1Stringstring constant fixes, and draft PR #1411 for thectkDICOMModalitiesAPI deprecation strategy.🤖 Generated with Claude Code