Skip to content

fix(headless): Set DX8Wrapper_IsWindowed to false to suppress assertion dialogs during shutdown#2298

Merged
xezon merged 5 commits intoTheSuperHackers:mainfrom
bobtista:bobtista/fix-headless-assert-dialogs
Mar 24, 2026
Merged

fix(headless): Set DX8Wrapper_IsWindowed to false to suppress assertion dialogs during shutdown#2298
xezon merged 5 commits intoTheSuperHackers:mainfrom
bobtista:bobtista/fix-headless-assert-dialogs

Conversation

@bobtista
Copy link
Copy Markdown

@bobtista bobtista commented Feb 12, 2026

Summary

  • Set DX8Wrapper_IsWindowed to false in headless mode so ignoringAsserts() works - particularly during shutdown after TheGlobalData has been destroyed.

Testing

  • Run headless replay to completion (-replay test.rep -headless -ignoreAsserts)
  • Verify no assertion dialogs appear during shutdown
  • Replicate in Generals

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Feb 12, 2026

Greptile Summary

This PR fixes spurious assertion dialogs that appeared during headless shutdown after TheGlobalData was destroyed. The root cause is in ignoringAsserts() (Core/GameEngine/Source/Common/System/Debug.cpp): it checks !DX8Wrapper_IsWindowed first, and only falls back to TheGlobalData && TheGlobalData->m_headless as a second path. Since DX8Wrapper_IsWindowed defaults to true and is never set to false in headless mode (because the graphics subsystem is never initialized), the first check fails; the second check also fails after TheGlobalData is destroyed during shutdown, resulting in ignoringAsserts() returning false and dialogs being shown.

Setting DX8Wrapper_IsWindowed = false in parseHeadless() before graphics initialization ensures ignoringAsserts() always returns true via the unconditional first path for the entire process lifetime in headless mode. The identical fix is applied to both Generals/ and GeneralsMD/ as expected.

  • The function-local extern bool DX8Wrapper_IsWindowed; declaration is unconventional but consistent with the pattern used at file scope in Debug.cpp and GameEngine.cpp for the same variable, and is well-supported by the C++ standard.
  • No risk of a later call overriding this back to true in headless mode because DX8Wrapper::Set_Render_Device() — the only other writer — is never invoked when graphics are disabled.

Confidence Score: 5/5

  • Safe to merge — minimal, targeted fix with no side-effects in non-headless paths.
  • The change is a single-line assignment in an isolated startup-time function, only reachable via the -headless command-line flag. The logic is directly traceable through ignoringAsserts() and the global's definition and all writers. Both game variants are updated identically, testing is documented in the PR, and there are no issues with custom rules or code style.
  • No files require special attention.

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Source/Common/CommandLine.cpp Adds explicit DX8Wrapper_IsWindowed = false in parseHeadless() so ignoringAsserts() suppresses assertion dialogs during shutdown even after TheGlobalData is destroyed.
GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp Identical fix mirrored from Generals/ — sets DX8Wrapper_IsWindowed = false in parseHeadless() for Zero Hour.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["-headless flag parsed\nparseHeadless()"] -->|before this PR| B["DX8Wrapper_IsWindowed\nremains true (default)"]
    A -->|after this PR| C["DX8Wrapper_IsWindowed = false"]

    B --> D["ignoringAsserts() called\nduring shutdown"]
    C --> D

    D --> E{DX8Wrapper_IsWindowed\n== false?}
    E -->|Yes - after fix| F["return true\n✅ Assert suppressed"]
    E -->|No - before fix| G{TheGlobalData &&\nm_headless?}
    G -->|TheGlobalData == nullptr\nduring shutdown| H["return false\n❌ Dialog shown"]
    G -->|TheGlobalData alive| I["return true\n✅ Assert suppressed"]
Loading

Reviews (4): Last reviewed commit: "Replicate headless DX8Wrapper_IsWindowed..." | Re-trigger Greptile

@xezon xezon added Debug Is mostly debug functionality Fix Is fixing something, but is not user facing labels Feb 27, 2026
Copy link
Copy Markdown

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be replicated to Generals.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 9, 2026

⚠️ Title/Commit Validation Failed

Invalid commit messages:

  • Move DX8Wrapper_IsWindowed headless fix into parseHeadless function
  • nit: date format in comment
  • Add braces around else-if body for style consistency
    PR titles and commit messages must follow conventional commits format:
type: Description
type(scope): Description

Allowed types: bugfix, build, chore, ci, docs, fix, feat, perf, refactor, revert, style, test, tweak, unify

See CONTRIBUTING.md for details.

@xezon xezon merged commit 08b8420 into TheSuperHackers:main Mar 24, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Debug Is mostly debug functionality Fix Is fixing something, but is not user facing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants