diff --git a/.github/workflows/ci_diag_sequential_lib_load.py b/.github/workflows/ci_diag_sequential_lib_load.py new file mode 100644 index 00000000000..920d4f13ea1 --- /dev/null +++ b/.github/workflows/ci_diag_sequential_lib_load.py @@ -0,0 +1,28 @@ +"""CI diagnostic, not for merge. + +Imports every grass.lib.* ctypes submodule one at a time in a single +process, flushing progress after each import, to find exactly how many +(and which) sequential ctypes library loads it takes to reproduce the +"Windows fatal exception: code 0xc0000139" crash seen under +pytest-xdist. A plain `python -c "from grass.pygrass import utils"` +in a single fresh process (see the sibling diagnostic PR) does not +crash, so this checks whether the crash is tied to the number of +distinct DLLs loaded cumulatively within one process. +""" + +import faulthandler +import pkgutil + +faulthandler.enable() + +import grass.lib # noqa: E402 + +modules = sorted(m.name for m in pkgutil.iter_modules(grass.lib.__path__)) +print(f"Found {len(modules)} grass.lib submodules: {modules}", flush=True) + +for i, name in enumerate(modules, 1): + print(f"[{i}/{len(modules)}] importing grass.lib.{name} ...", flush=True) + __import__(f"grass.lib.{name}") + print(f"[{i}/{len(modules)}] OK", flush=True) + +print("ALL grass.lib submodules imported successfully", flush=True) diff --git a/.github/workflows/osgeo4w.yml b/.github/workflows/osgeo4w.yml index 96b5a6bb9aa..4549ec77417 100644 --- a/.github/workflows/osgeo4w.yml +++ b/.github/workflows/osgeo4w.yml @@ -124,6 +124,24 @@ jobs: shell: msys2 {0} run: .github/workflows/test_simple.sh + - name: "[CI diagnostic, not for merge] Sequential grass.lib load count" + # A plain single import of grass.pygrass.utils (which loads + # grass_gis.8.6.dll) does not crash in isolation (see the sibling + # standalone-import-test PR), but the same load crashes with + # "Windows fatal exception: code 0xc0000139" under pytest-xdist. + # This imports every grass.lib.* ctypes submodule one at a time + # in a single process to see whether the crash is tied to the + # number of distinct DLLs accumulated as loaded in one process + # (e.g. a Windows/MinGW TLS-slot exhaustion), and if so, exactly + # how many/which imports it takes to trigger it. + run: | + call %OSGEO4W_ROOT%\opt\grass\etc\env.bat + set PYTHONPATH=%GISBASE%\etc\python;%PYTHONPATH% + path %GISBASE%\lib;%GISBASE%\bin;%PATH% + python .github/workflows/ci_diag_sequential_lib_load.py + # Obfuscated usage of GitHub Actions features, Windows CMD shell limits analysis + shell: cmd /D /E:ON /V:OFF /S /C "CALL C:/OSGeo4W/OSGeo4W.bat "{0}"" # zizmor: ignore[misfeature] + - name: Install additional python packages run: | python -m pip install ^