Commit 50e4410
authored
FIX: Static UUID variable causes pytest crash (#271)
### Work Item / Issue Reference
<!--
IMPORTANT: Please follow the PR template guidelines below.
For mssql-python maintainers: Insert your ADO Work Item ID below (e.g.
AB#37452)
For external contributors: Insert Github Issue number below (e.g. #149)
Only one reference is required - either GitHub issue OR ADO Work Item.
-->
<!-- mssql-python maintainers: ADO Work Item -->
>
[AB#39063](https://sqlclientdrivers.visualstudio.com/c6d89619-62de-46a0-8b46-70b92a84d85e/_workitems/edit/39063)
-------------------------------------------------------------------
### Summary
<!-- Insert your summary of changes below. Minimum 10 characters
required. -->
## Problem
Pytest test suite (335+ tests) was crashing on exit with:
```
Fatal Python error: _Py_GetConfig: the function must be called with the GIL held,
after Python initialization and before Python finalization, but the GIL is released
```
The crash occurred **after all tests passed**, during Python shutdown on
Windows x64 and macOS.
## Root Cause
Static `pybind11::module_` and `pybind11::object` instances in
`BindParameterArray()` function (lines 2072-2073) were being destroyed
during C++ static destruction phase, which happens **after** Python has
released the GIL and begun finalization.
When the destructors called `Py_XDECREF`, Python's `_Py_GetConfig()` was
invoked without the GIL, causing the fatal error.
```cpp
// OLD CODE - Problematic static objects
static py::module_ uuid_mod = py::module_::import("uuid");
static py::object uuid_class = uuid_mod.attr("UUID");
```
## Solution
Moved UUID class caching to module initialization level using a helper
function. This ensures the Python object lifecycle is managed within
pybind11's module context, avoiding destructor calls during
finalization.
```cpp
// NEW CODE - Module-level cached helper
py::object uuid_class = py::module_::import("mssql_python.ddbc_bindings").attr("_get_uuid_class")();
```
The `_get_uuid_class()` helper is defined at module initialization and
maintains a static cache that lives for the module's lifetime, properly
integrated with pybind11's lifecycle management.
## Testing
- ✅ Full test suite (335+ tests) now completes without crash on macOS
- ✅ Exit code 0 after pytest completion
- ✅ No functionality changes - UUID parameter binding works identically
## Impact
- **Platforms affected**: Windows x64, macOS (all platforms with the
issue)
- **Risk**: Low - surgical fix, no behavioral changes
- **Files changed**: 1 file, ~15 lines added/modified1 parent 7e65290 commit 50e4410
1 file changed
+12
-2
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2069 | 2069 | | |
2070 | 2070 | | |
2071 | 2071 | | |
2072 | | - | |
2073 | | - | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
2074 | 2076 | | |
2075 | 2077 | | |
2076 | 2078 | | |
| |||
3903 | 3905 | | |
3904 | 3906 | | |
3905 | 3907 | | |
| 3908 | + | |
| 3909 | + | |
| 3910 | + | |
| 3911 | + | |
| 3912 | + | |
| 3913 | + | |
| 3914 | + | |
| 3915 | + | |
3906 | 3916 | | |
3907 | 3917 | | |
3908 | 3918 | | |
| |||
0 commit comments