Skip to content

Commit 5084036

Browse files
ychinchrisbra
authored andcommitted
patch 9.1.0726: not using correct python3 API with dynamic linking
Problem: not using correct python3 API with dynamic linking Solution: Use stable IncRef / DecRef in Python 3 dynamic bindings (Yee Cheng Chin) Previously, we were using the Py_DECREF macros even when using dynamic linking of Python 3. This caused issues because Python's headers contain references to internal APIs like `_Py_Dealloc` and in v8.1.2201 and v8.2.1225 we simply hacked around the issue by manually copying the Python header implementation to Vim and linking in the private APIs. This is fragile and prone to break. In fact, the Py_DECREF implementation is different in newer versions of Python meaning that this could potentially cause memory issues. Instead, simply use the API versions (`Py_DECREF` and `Py_INCREF`) which are functions exposed by the Python library. They could be slightly slower since they require a function call instead of a macro, but are much more reliable and we should only be calling these when the Python Vim plugins are crossing the language boundary anyway which are always going to be slow. Note that this only affects dynamically linked Python builds that are not using stable ABI. Also see #15648 closes: #15653 Signed-off-by: Yee Cheng Chin <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent c0982f9 commit 5084036

2 files changed

Lines changed: 12 additions & 48 deletions

File tree

src/if_python3.c

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static HINSTANCE hinstPy3 = 0; // Instance of python.dll
219219
# define PyObject_GetItem py3_PyObject_GetItem
220220
# define PyObject_IsTrue py3_PyObject_IsTrue
221221
# define PyModule_GetDict py3_PyModule_GetDict
222-
# ifdef USE_LIMITED_API
222+
# if defined(USE_LIMITED_API) || PY_VERSION_HEX >= 0x03080000
223223
# define Py_IncRef py3_Py_IncRef
224224
# define Py_DecRef py3_Py_DecRef
225225
# endif
@@ -293,9 +293,6 @@ static HINSTANCE hinstPy3 = 0; // Instance of python.dll
293293
# define PyBytes_FromString py3_PyBytes_FromString
294294
# undef PyBytes_FromStringAndSize
295295
# define PyBytes_FromStringAndSize py3_PyBytes_FromStringAndSize
296-
# if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 || defined(USE_LIMITED_API)
297-
# define _Py_Dealloc py3__Py_Dealloc
298-
# endif
299296
# define PyFloat_FromDouble py3_PyFloat_FromDouble
300297
# define PyFloat_AsDouble py3_PyFloat_AsDouble
301298
# define PyObject_GenericGetAttr py3_PyObject_GenericGetAttr
@@ -396,7 +393,7 @@ static void (*py3_Py_Finalize)(void);
396393
static void (*py3_PyErr_SetString)(PyObject *, const char *);
397394
static void (*py3_PyErr_SetObject)(PyObject *, PyObject *);
398395
static int (*py3_PyErr_ExceptionMatches)(PyObject *);
399-
# ifdef USE_LIMITED_API
396+
# if defined(USE_LIMITED_API) || PY_VERSION_HEX >= 0x03080000
400397
static void (*py3_Py_IncRef)(PyObject *);
401398
static void (*py3_Py_DecRef)(PyObject *);
402399
# endif
@@ -497,9 +494,6 @@ static char* (*py3_PyBytes_AsString)(PyObject *bytes);
497494
static int (*py3_PyBytes_AsStringAndSize)(PyObject *bytes, char **buffer, Py_ssize_t *length);
498495
static PyObject* (*py3_PyBytes_FromString)(char *str);
499496
static PyObject* (*py3_PyBytes_FromStringAndSize)(char *str, Py_ssize_t length);
500-
# if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 || defined(USE_LIMITED_API)
501-
static void (*py3__Py_Dealloc)(PyObject *obj);
502-
# endif
503497
# if PY_VERSION_HEX >= 0x030900b0
504498
static PyObject* (*py3__PyObject_New)(PyTypeObject *);
505499
# endif
@@ -607,7 +601,7 @@ static struct
607601
{"PyErr_SetString", (PYTHON_PROC*)&py3_PyErr_SetString},
608602
{"PyErr_SetObject", (PYTHON_PROC*)&py3_PyErr_SetObject},
609603
{"PyErr_ExceptionMatches", (PYTHON_PROC*)&py3_PyErr_ExceptionMatches},
610-
# ifdef USE_LIMITED_API
604+
# if defined(USE_LIMITED_API) || PY_VERSION_HEX >= 0x03080000
611605
{"Py_IncRef", (PYTHON_PROC*)&py3_Py_IncRef},
612606
{"Py_DecRef", (PYTHON_PROC*)&py3_Py_DecRef},
613607
# endif
@@ -702,9 +696,6 @@ static struct
702696
{"PyBytes_AsStringAndSize", (PYTHON_PROC*)&py3_PyBytes_AsStringAndSize},
703697
{"PyBytes_FromString", (PYTHON_PROC*)&py3_PyBytes_FromString},
704698
{"PyBytes_FromStringAndSize", (PYTHON_PROC*)&py3_PyBytes_FromStringAndSize},
705-
# if defined(Py_DEBUG) || PY_VERSION_HEX >= 0x030900b0 || defined(USE_LIMITED_API)
706-
{"_Py_Dealloc", (PYTHON_PROC*)&py3__Py_Dealloc},
707-
# endif
708699
# if PY_VERSION_HEX >= 0x030900b0
709700
{"_PyObject_New", (PYTHON_PROC*)&py3__PyObject_New},
710701
# endif
@@ -752,44 +743,15 @@ static struct
752743
{"", NULL},
753744
};
754745

755-
# if PY_VERSION_HEX >= 0x030800f0
756-
static inline void
757-
py3__Py_DECREF(const char *filename UNUSED, int lineno UNUSED, PyObject *op)
758-
{
759-
if (--op->ob_refcnt != 0)
760-
{
761-
# ifdef Py_REF_DEBUG
762-
if (op->ob_refcnt < 0)
763-
{
764-
_Py_NegativeRefcount(filename, lineno, op);
765-
}
766-
# endif
767-
}
768-
else
769-
{
770-
_Py_Dealloc(op);
771-
}
772-
}
773-
774-
# undef Py_DECREF
775-
# define Py_DECREF(op) py3__Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
776-
777-
static inline void
778-
py3__Py_XDECREF(PyObject *op)
779-
{
780-
if (op != NULL)
781-
{
782-
Py_DECREF(op);
783-
}
784-
}
785-
786-
# undef Py_XDECREF
787-
# define Py_XDECREF(op) py3__Py_XDECREF(_PyObject_CAST(op))
788-
# endif
789-
790-
# ifdef USE_LIMITED_API
746+
# if defined(USE_LIMITED_API) || PY_VERSION_HEX >= 0x03080000
791747
// Use stable versions of inc/dec ref. Note that these always null-check and
792748
// therefore there's no difference between XINCREF and INCREF.
749+
//
750+
// For 3.8 or above, we also use this version even if not using limited API.
751+
// The Py_DECREF macros in 3.8+ include references to internal functions which
752+
// cause link errors when building Vim. The stable versions are exposed as API
753+
// functions and don't have these problems (albeit slightly slower as they
754+
// require function calls rather than an inlined macro).
793755
# undef Py_INCREF
794756
# define Py_INCREF(obj) Py_IncRef((PyObject *)obj)
795757
# undef Py_XINCREF

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,8 @@ static char *(features[]) =
704704

705705
static int included_patches[] =
706706
{ /* Add new patch number below this line */
707+
/**/
708+
726,
707709
/**/
708710
725,
709711
/**/

0 commit comments

Comments
 (0)