diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59466c093..d8a33d4aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,12 +70,6 @@ jobs: python: pypy3 arch: x64 - # TODO: renable - # Currently segfaults on macOS Python 3.9 - - runs-on: macos-latest - python: 3.9 - arch: x64 - name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • ${{ matrix.arch }} ${{ matrix.args }}" runs-on: ${{ matrix.runs-on }} diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index da682ea70..8698390e0 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -452,6 +452,12 @@ protected: /// When a cpp_function is GCed, release any memory allocated by pybind11 static void destruct(detail::function_record *rec) { + // If on Python 3.9, check the interpreter "MICRO" (patch) version. + // If this is running on 3.9.0, we have to work around a bug. + #if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9 + static bool is_zero = Py_GetVersion()[4] == '0'; + #endif + while (rec) { detail::function_record *next = rec->next; if (rec->free_data) @@ -466,7 +472,15 @@ protected: } if (rec->def) { std::free(const_cast(rec->def->ml_doc)); - delete rec->def; + // Python 3.9.0 decref's these in the wrong order; rec->def + // If loaded on 3.9.0, let these leak (use Python 3.9.1 at runtime to fix) + // See https://github.com/python/cpython/pull/22670 + #if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9 + if (!is_zero) + delete rec->def; + #else + delete rec->def; + #endif } delete rec; rec = next;