Skip to content

Commit 9d7acfe

Browse files
committed
Add verbose DLL diagnostics to debug GHA segfault during Python init
1 parent e39a8cc commit 9d7acfe

2 files changed

Lines changed: 59 additions & 13 deletions

File tree

Libs/Application/Job/PythonWorker.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,40 @@ bool PythonWorker::init() {
246246
QString current_path = qgetenv("PATH");
247247
qputenv("PATH", (dlls_dir + ";" + python_home + ";" + app_dir + ";" + current_path).toUtf8());
248248

249+
// Verbose diagnostics for debugging GHA failures
250+
std::cerr << "=== Bundled Python DLL diagnostics ===\n";
251+
std::cerr << " app_dir: " << app_dir.toStdString() << "\n";
252+
std::cerr << " python_home: " << python_home.toStdString() << "\n";
253+
std::cerr << " DLLs dir: " << dlls_dir.toStdString() << "\n";
254+
std::cerr << " DLLs dir exists: " << QDir(dlls_dir).exists() << "\n";
255+
std::cerr << " python_home/Library/bin exists: " << QDir(python_home + "/Library/bin").exists() << "\n";
256+
257+
// Check critical files
258+
QStringList check_files = {
259+
python_home + "/python312.dll",
260+
python_home + "/python3.dll",
261+
python_home + "/DLLs/pyexpat.pyd",
262+
python_home + "/Library/bin/libexpat.dll",
263+
python_home + "/Lib/os.py",
264+
app_dir + "/python312.dll",
265+
app_dir + "/libexpat.dll",
266+
};
267+
for (const auto& f : check_files) {
268+
std::cerr << " " << f.toStdString() << " : " << (QFile::exists(f) ? "EXISTS" : "MISSING") << "\n";
269+
}
270+
271+
// List DLLs in app_dir matching python* or lib*
272+
QDir app_dir_obj(app_dir);
273+
QStringList dll_filters = {"python*.dll", "lib*.dll"};
274+
auto dlls_in_app = app_dir_obj.entryList(dll_filters, QDir::Files);
275+
std::cerr << " DLLs in app_dir: ";
276+
for (const auto& d : dlls_in_app) std::cerr << d.toStdString() << " ";
277+
std::cerr << "\n";
278+
279+
std::cerr << " PATH (first 500 chars): " << qgetenv("PATH").left(500).toStdString() << "\n";
280+
std::cerr << "=== End diagnostics ===\n";
281+
std::cerr.flush();
282+
249283
SW_LOG("Registered bundled Python DLL directories");
250284
} else {
251285
// Legacy conda-based Python path
@@ -284,7 +318,11 @@ bool PythonWorker::init() {
284318
#endif // ifdef _WIN32
285319

286320
try {
321+
std::cerr << "=== About to call py::initialize_interpreter() ===\n";
322+
std::cerr.flush();
287323
py::initialize_interpreter();
324+
std::cerr << "=== py::initialize_interpreter() succeeded ===\n";
325+
std::cerr.flush();
288326
interpreter_started_ = true;
289327

290328
py::module sys = py::module::import("sys");

cmake/BundledPython.cmake

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,28 @@ if(WIN32)
107107
set(_conda_prefix "${_conda_prefix}")
108108
message(STATUS "Windows: skipping conda extension copy (bundled Python has its own DLLs)")
109109

110-
# Copy conda's Library/bin DLLs to the build output directory so the embedded
111-
# interpreter can find them. Conda's .pyd extensions (pyexpat, _ssl, etc.) have
112-
# implicit DLL dependencies (libexpat, libssl, etc.) in Library/bin/. In the
113-
# build tree, the application directory is always searched for DLLs, so placing
114-
# them next to the executables is the most reliable approach.
110+
# Copy specific conda DLLs needed by Python's .pyd extensions to the build
111+
# output directory. Conda's .pyd extensions (pyexpat, _ssl, etc.) have implicit
112+
# DLL dependencies in Library/bin/. We only copy the Python-specific ones to
113+
# avoid conflicting with Qt/VTK/Boost DLLs already in the build directory.
115114
set(_conda_lib_bin "${_conda_prefix}/Library/bin")
116-
if(EXISTS "${_conda_lib_bin}")
117-
file(GLOB _conda_dlls "${_conda_lib_bin}/*.dll")
118-
list(LENGTH _conda_dlls _num_dlls)
119-
message(STATUS "Copying ${_num_dlls} DLLs from conda Library/bin to build output")
120-
file(COPY ${_conda_dlls} DESTINATION "${CMAKE_BINARY_DIR}/bin/Release")
121-
# Also copy to bin/ for NMake builds
122-
file(COPY ${_conda_dlls} DESTINATION "${CMAKE_BINARY_DIR}/bin")
123-
endif()
115+
set(_python_dep_dlls
116+
libexpat.dll # pyexpat.pyd
117+
libssl-3-x64.dll # _ssl.pyd
118+
libcrypto-3-x64.dll # _hashlib.pyd
119+
libffi-8.dll # _ctypes.pyd (if present)
120+
zlib.dll # zlib module
121+
libbz2.dll # _bz2.pyd
122+
liblzma.dll # _lzma.pyd
123+
sqlite3.dll # _sqlite3.pyd
124+
)
125+
foreach(_dll ${_python_dep_dlls})
126+
if(EXISTS "${_conda_lib_bin}/${_dll}")
127+
message(STATUS "Copying ${_dll} from conda Library/bin to build output")
128+
file(COPY "${_conda_lib_bin}/${_dll}" DESTINATION "${CMAKE_BINARY_DIR}/bin/Release")
129+
file(COPY "${_conda_lib_bin}/${_dll}" DESTINATION "${CMAKE_BINARY_DIR}/bin")
130+
endif()
131+
endforeach()
124132
else()
125133
get_filename_component(_conda_prefix "${_conda_prefix}" DIRECTORY) # .../
126134
set(_conda_lib_dynload "${_conda_prefix}/lib/python3.12/lib-dynload")

0 commit comments

Comments
 (0)