Skip to content

CI: [diagnostic, do not merge] Capture Windows loader snaps to pinpoint the crash - #713

Closed
echoix wants to merge 4 commits into
mainfrom
ci-diag-loader-snaps
Closed

echoix wants to merge 4 commits into
mainfrom
ci-diag-loader-snaps

Conversation

@echoix

@echoix echoix commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Purpose

Answers a direct question in this investigation: rather than keep
manually diffing binaries, ask Windows' own loader what's actually
failing.

An exhaustive, offline symbol-level cross-check now covers essentially
grass_gis.8.6.dll's entire non-system dependency closure:
gdal313.dll, curl, OpenSSL (libssl/libcrypto), libjpeg-turbo, expat,
PROJ, sqlite3, libxml2, brotli, zstd, msvcrt2019, and most
MSYS2-provided libraries (libbz2-1, libiconv-2, libintl-8, zlib1) --
every symbol each of these 14+ DLLs imports from any of the others is
present in the providing DLL's export table. (Note: a modern
Dependency Walker replacement like lucasg/Dependencies was considered,
but it only resolves at the DLL-file level, not the per-symbol level,
so it wouldn't catch this class of issue -- confirmed by reading its
resolution source directly.)

What this PR does

  1. Dumps the real `libgomp-1.dll`/`libsystre-0.dll` exports directly
    from the CI environment (the two MSYS2 libraries only spot-checked
    locally so far, against a non-identical build).
  2. Enables Windows Loader Snaps for `python.exe` via the Image File
    Execution Options `GlobalFlag` registry key, captures the trace
    with Sysinternals DebugView, and runs `python -m pytest` (which
    reliably crashes with `Windows fatal exception: code 0xc0000139`)
    underneath it. This should show, directly from the OS loader
    itself, the exact module and symbol resolution step that fails.

This PR is for CI investigation only and is not meant to be merged.

🤖 Generated with Claude Code

…(not for merge)

An exhaustive, cross-checked symbol-level graph covering
grass_gis.8.6.dll's entire dependency closure -- gdal313.dll, curl,
OpenSSL (libssl/libcrypto), libjpeg-turbo, expat, PROJ, sqlite3,
libxml2, brotli, zstd, msvcrt2019, and most MSYS2-provided libraries --
comes back completely clean: every symbol each of these needs from any
of the others is present. Rather than keep guessing which single
binary might have an unresolved symbol, this asks Windows' own loader
directly.

Enables Loader Snaps (verbose OS-level trace of every module load and
symbol resolution step) for python.exe via the Image File Execution
Options GlobalFlag, captures it with Sysinternals DebugView, and runs
`python -m pytest` (which reliably crashes with "Windows fatal
exception: code 0xc0000139") underneath it. Also dumps the real
libgomp-1.dll/libsystre-0.dll exports directly from the CI environment,
completing the dependency graph check (only spot-checked locally
against non-identical builds so far).

Temporary, for CI investigation only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
echoix and others added 3 commits September 26, 2026 12:10
The previous version wrapped the actual `python -m pytest` invocation
in a PowerShell string passed through `& "OSGeo4W.bat" cmd /c $cmd`,
which corrupted the huge %PATH% value during the nested cmd.exe
re-invocation ("\NSIS\ was unexpected at this time"), so python never
actually ran inside the loader-snaps capture window at all -- the
step produced no log and errored out before testing anything.

This splits the diagnostic into three steps: start DebugView/enable
loader snaps (PowerShell), run python -m pytest using the exact same
proven cmd/OSGeo4W.bat wrapper every other pytest step in this
workflow already uses, then stop DebugView and dump the trace
(PowerShell). Confirmed via a previous run of this PR: every native
dependency in grass_gis.8.6.dll's dependency graph (GDAL, curl,
OpenSSL, libjpeg-turbo, expat, PROJ, sqlite3, libxml2, brotli, zstd,
msvcrt2019, and now all 6 MSYS2-provided libraries pulled directly
from the CI environment) is symbol-level clean, so this is the last
remaining way to directly identify the actual failure without
guessing further.

Temporary, for CI investigation only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… merge)

The previous run's crash reproduced correctly under the capture window,
but the loader snaps log came back empty. Windows Loader Snaps are
emitted through the kernel-mode DbgPrint path, not Win32
OutputDebugString, and DebugView only listens to DbgPrint when its /k
(capture kernel) switch is passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rge)

DebugView never produced a log file at all, with or without kernel
capture enabled, most likely because GitHub Actions runs steps in a
non-interactive Session 0 where its GUI message pump cannot
initialize. cdb.exe (the console-mode debugger from the Windows SDK
Debugging Tools) is itself a debugger attached directly to the
python.exe process, which is the OS-level sink loader snaps are meant
to write to, and needs no desktop session at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@echoix echoix closed this Sep 30, 2026
@echoix
echoix deleted the ci-diag-loader-snaps branch September 30, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant