forked from aniani/vim
updated for version 7.3.998
Problem: Python: garbage collection issues. Solution: Fix the GC issues: Use proper DESTRUCTOR_FINISH: avoids negative refcounts, use PyObject_GC_* for objects with tp_traverse and tp_clear, add RangeTraverse and RangeClear, use Py_XDECREF in some places. (ZyX)
This commit is contained in:
@@ -461,7 +461,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
|
VimEval(PyObject *self UNUSED, PyObject *args)
|
||||||
{
|
{
|
||||||
char *expr;
|
char *expr;
|
||||||
typval_T *our_tv;
|
typval_T *our_tv;
|
||||||
@@ -602,7 +602,7 @@ IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
|||||||
{
|
{
|
||||||
IterObject *self;
|
IterObject *self;
|
||||||
|
|
||||||
self = PyObject_NEW(IterObject, &IterType);
|
self = PyObject_GC_New(IterObject, &IterType);
|
||||||
self->cur = start;
|
self->cur = start;
|
||||||
self->next = next;
|
self->next = next;
|
||||||
self->destruct = destruct;
|
self->destruct = destruct;
|
||||||
@@ -615,9 +615,9 @@ IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
|
|||||||
static void
|
static void
|
||||||
IterDestructor(IterObject *self)
|
IterDestructor(IterObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack((void *)(self));
|
||||||
self->destruct(self->cur);
|
self->destruct(self->cur);
|
||||||
|
PyObject_GC_Del((void *)(self));
|
||||||
DESTRUCTOR_FINISH(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1414,7 +1414,7 @@ OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
|
|||||||
{
|
{
|
||||||
OptionsObject *self;
|
OptionsObject *self;
|
||||||
|
|
||||||
self = PyObject_NEW(OptionsObject, &OptionsType);
|
self = PyObject_GC_New(OptionsObject, &OptionsType);
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1431,9 +1431,9 @@ OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
|
|||||||
static void
|
static void
|
||||||
OptionsDestructor(OptionsObject *self)
|
OptionsDestructor(OptionsObject *self)
|
||||||
{
|
{
|
||||||
if (self->fromObj)
|
PyObject_GC_UnTrack((void *)(self));
|
||||||
Py_DECREF(self->fromObj);
|
Py_XDECREF(self->fromObj);
|
||||||
DESTRUCTOR_FINISH(self);
|
PyObject_GC_Del((void *)(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1869,7 +1869,7 @@ WindowNew(win_T *win, tabpage_T *tab)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self = PyObject_NEW(WindowObject, &WindowType);
|
self = PyObject_GC_New(WindowObject, &WindowType);
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
self->win = win;
|
self->win = win;
|
||||||
@@ -1884,12 +1884,25 @@ WindowNew(win_T *win, tabpage_T *tab)
|
|||||||
static void
|
static void
|
||||||
WindowDestructor(WindowObject *self)
|
WindowDestructor(WindowObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack((void *)(self));
|
||||||
if (self->win && self->win != INVALID_WINDOW_VALUE)
|
if (self->win && self->win != INVALID_WINDOW_VALUE)
|
||||||
WIN_PYTHON_REF(self->win) = NULL;
|
WIN_PYTHON_REF(self->win) = NULL;
|
||||||
|
Py_XDECREF(((PyObject *)(self->tabObject)));
|
||||||
|
PyObject_GC_Del((void *)(self));
|
||||||
|
}
|
||||||
|
|
||||||
Py_DECREF(((PyObject *)(self->tabObject)));
|
static int
|
||||||
|
WindowTraverse(WindowObject *self, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(((PyObject *)(self->tabObject)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DESTRUCTOR_FINISH(self);
|
static int
|
||||||
|
WindowClear(WindowObject *self)
|
||||||
|
{
|
||||||
|
Py_CLEAR(self->tabObject);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static win_T *
|
static win_T *
|
||||||
@@ -1909,19 +1922,6 @@ get_firstwin(TabPageObject *tabObject)
|
|||||||
else
|
else
|
||||||
return firstwin;
|
return firstwin;
|
||||||
}
|
}
|
||||||
static int
|
|
||||||
WindowTraverse(WindowObject *self, visitproc visit, void *arg)
|
|
||||||
{
|
|
||||||
Py_VISIT(((PyObject *)(self->tabObject)));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
WindowClear(WindowObject *self)
|
|
||||||
{
|
|
||||||
Py_CLEAR(self->tabObject);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
WindowAttr(WindowObject *self, char *name)
|
WindowAttr(WindowObject *self, char *name)
|
||||||
@@ -2917,7 +2917,7 @@ RangeNew(buf_T *buf, PyInt start, PyInt end)
|
|||||||
{
|
{
|
||||||
BufferObject *bufr;
|
BufferObject *bufr;
|
||||||
RangeObject *self;
|
RangeObject *self;
|
||||||
self = PyObject_NEW(RangeObject, &RangeType);
|
self = PyObject_GC_New(RangeObject, &RangeType);
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -2939,8 +2939,23 @@ RangeNew(buf_T *buf, PyInt start, PyInt end)
|
|||||||
static void
|
static void
|
||||||
RangeDestructor(RangeObject *self)
|
RangeDestructor(RangeObject *self)
|
||||||
{
|
{
|
||||||
|
PyObject_GC_UnTrack((void *)(self));
|
||||||
Py_XDECREF(self->buf);
|
Py_XDECREF(self->buf);
|
||||||
DESTRUCTOR_FINISH(self);
|
PyObject_GC_Del((void *)(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
RangeTraverse(RangeObject *self, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
Py_VISIT(((PyObject *)(self->buf)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
RangeClear(RangeObject *self)
|
||||||
|
{
|
||||||
|
Py_CLEAR(self->buf);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyInt
|
static PyInt
|
||||||
@@ -3267,6 +3282,7 @@ BufMapIterDestruct(PyObject *buffer)
|
|||||||
static int
|
static int
|
||||||
BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
|
BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
|
if (buffer)
|
||||||
Py_VISIT(buffer);
|
Py_VISIT(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3274,6 +3290,7 @@ BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
|
|||||||
static int
|
static int
|
||||||
BufMapIterClear(PyObject **buffer)
|
BufMapIterClear(PyObject **buffer)
|
||||||
{
|
{
|
||||||
|
if (*buffer)
|
||||||
Py_CLEAR(*buffer);
|
Py_CLEAR(*buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -4144,6 +4161,8 @@ init_structs(void)
|
|||||||
RangeType.tp_flags = Py_TPFLAGS_DEFAULT;
|
RangeType.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||||
RangeType.tp_doc = "vim Range object";
|
RangeType.tp_doc = "vim Range object";
|
||||||
RangeType.tp_methods = RangeMethods;
|
RangeType.tp_methods = RangeMethods;
|
||||||
|
RangeType.tp_traverse = (traverseproc)RangeTraverse;
|
||||||
|
RangeType.tp_clear = (inquiry)RangeClear;
|
||||||
#if PY_MAJOR_VERSION >= 3
|
#if PY_MAJOR_VERSION >= 3
|
||||||
RangeType.tp_getattro = (getattrofunc)RangeGetattro;
|
RangeType.tp_getattro = (getattrofunc)RangeGetattro;
|
||||||
RangeType.tp_alloc = call_PyType_GenericAlloc;
|
RangeType.tp_alloc = call_PyType_GenericAlloc;
|
||||||
|
@@ -224,6 +224,9 @@ struct PyMethodDef { Py_ssize_t a; };
|
|||||||
# define Py_Finalize dll_Py_Finalize
|
# define Py_Finalize dll_Py_Finalize
|
||||||
# define Py_IsInitialized dll_Py_IsInitialized
|
# define Py_IsInitialized dll_Py_IsInitialized
|
||||||
# define _PyObject_New dll__PyObject_New
|
# define _PyObject_New dll__PyObject_New
|
||||||
|
# define _PyObject_GC_New dll__PyObject_GC_New
|
||||||
|
# define PyObject_GC_Del dll_PyObject_GC_Del
|
||||||
|
# define PyObject_GC_UnTrack dll_PyObject_GC_UnTrack
|
||||||
# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000
|
# if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02070000
|
||||||
# define _PyObject_NextNotImplemented (*dll__PyObject_NextNotImplemented)
|
# define _PyObject_NextNotImplemented (*dll__PyObject_NextNotImplemented)
|
||||||
# endif
|
# endif
|
||||||
@@ -331,6 +334,9 @@ static void(*dll_Py_Initialize)(void);
|
|||||||
static void(*dll_Py_Finalize)(void);
|
static void(*dll_Py_Finalize)(void);
|
||||||
static int(*dll_Py_IsInitialized)(void);
|
static int(*dll_Py_IsInitialized)(void);
|
||||||
static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
|
static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
|
||||||
|
static PyObject*(*dll__PyObject_GC_New)(PyTypeObject *);
|
||||||
|
static void(*dll_PyObject_GC_Del)(void *);
|
||||||
|
static void(*dll_PyObject_GC_UnTrack)(void *);
|
||||||
static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
|
static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
|
||||||
static PyObject* (*dll_PyObject_GetIter)(PyObject *);
|
static PyObject* (*dll_PyObject_GetIter)(PyObject *);
|
||||||
static int (*dll_PyObject_IsTrue)(PyObject *);
|
static int (*dll_PyObject_IsTrue)(PyObject *);
|
||||||
@@ -474,6 +480,9 @@ static struct
|
|||||||
{"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize},
|
{"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize},
|
||||||
{"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized},
|
{"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized},
|
||||||
{"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
|
{"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
|
||||||
|
{"_PyObject_GC_New", (PYTHON_PROC*)&dll__PyObject_GC_New},
|
||||||
|
{"PyObject_GC_Del", (PYTHON_PROC*)&dll_PyObject_GC_Del},
|
||||||
|
{"PyObject_GC_UnTrack", (PYTHON_PROC*)&dll_PyObject_GC_UnTrack},
|
||||||
{"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
|
{"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
|
||||||
{"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter},
|
{"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter},
|
||||||
{"PyObject_IsTrue", (PYTHON_PROC*)&dll_PyObject_IsTrue},
|
{"PyObject_IsTrue", (PYTHON_PROC*)&dll_PyObject_IsTrue},
|
||||||
@@ -632,7 +641,7 @@ static int initialised = 0;
|
|||||||
#define DICTKEY_UNREF
|
#define DICTKEY_UNREF
|
||||||
#define DICTKEY_DECL
|
#define DICTKEY_DECL
|
||||||
|
|
||||||
#define DESTRUCTOR_FINISH(self) Py_DECREF(self);
|
#define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self);
|
||||||
|
|
||||||
#define WIN_PYTHON_REF(win) win->w_python_ref
|
#define WIN_PYTHON_REF(win) win->w_python_ref
|
||||||
#define BUF_PYTHON_REF(buf) buf->b_python_ref
|
#define BUF_PYTHON_REF(buf) buf->b_python_ref
|
||||||
|
@@ -213,6 +213,9 @@
|
|||||||
# define PyObject_Malloc py3_PyObject_Malloc
|
# define PyObject_Malloc py3_PyObject_Malloc
|
||||||
# define PyObject_Free py3_PyObject_Free
|
# define PyObject_Free py3_PyObject_Free
|
||||||
# endif
|
# endif
|
||||||
|
# define _PyObject_GC_New py3__PyObject_GC_New
|
||||||
|
# define PyObject_GC_Del py3_PyObject_GC_Del
|
||||||
|
# define PyObject_GC_UnTrack py3_PyObject_GC_UnTrack
|
||||||
# define PyType_GenericAlloc py3_PyType_GenericAlloc
|
# define PyType_GenericAlloc py3_PyType_GenericAlloc
|
||||||
# define PyType_GenericNew py3_PyType_GenericNew
|
# define PyType_GenericNew py3_PyType_GenericNew
|
||||||
# define PyModule_Create2 py3_PyModule_Create2
|
# define PyModule_Create2 py3_PyModule_Create2
|
||||||
@@ -334,6 +337,9 @@ static void* (*py3_PyCapsule_GetPointer)(PyObject *, char *);
|
|||||||
static void (*py3_PyObject_Free)(void*);
|
static void (*py3_PyObject_Free)(void*);
|
||||||
static void* (*py3_PyObject_Malloc)(size_t);
|
static void* (*py3_PyObject_Malloc)(size_t);
|
||||||
# endif
|
# endif
|
||||||
|
static PyObject*(*py3__PyObject_GC_New)(PyTypeObject *);
|
||||||
|
static void(*py3_PyObject_GC_Del)(void *);
|
||||||
|
static void(*py3_PyObject_GC_UnTrack)(void *);
|
||||||
static int (*py3_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
|
static int (*py3_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
|
||||||
|
|
||||||
static HINSTANCE hinstPy3 = 0; /* Instance of python.dll */
|
static HINSTANCE hinstPy3 = 0; /* Instance of python.dll */
|
||||||
@@ -463,6 +469,9 @@ static struct
|
|||||||
{"PyObject_Malloc", (PYTHON_PROC*)&py3_PyObject_Malloc},
|
{"PyObject_Malloc", (PYTHON_PROC*)&py3_PyObject_Malloc},
|
||||||
{"PyObject_Free", (PYTHON_PROC*)&py3_PyObject_Free},
|
{"PyObject_Free", (PYTHON_PROC*)&py3_PyObject_Free},
|
||||||
# endif
|
# endif
|
||||||
|
{"_PyObject_GC_New", (PYTHON_PROC*)&py3__PyObject_GC_New},
|
||||||
|
{"PyObject_GC_Del", (PYTHON_PROC*)&py3_PyObject_GC_Del},
|
||||||
|
{"PyObject_GC_UnTrack", (PYTHON_PROC*)&py3_PyObject_GC_UnTrack},
|
||||||
{"PyType_IsSubtype", (PYTHON_PROC*)&py3_PyType_IsSubtype},
|
{"PyType_IsSubtype", (PYTHON_PROC*)&py3_PyType_IsSubtype},
|
||||||
{"PyCapsule_New", (PYTHON_PROC*)&py3_PyCapsule_New},
|
{"PyCapsule_New", (PYTHON_PROC*)&py3_PyCapsule_New},
|
||||||
{"PyCapsule_GetPointer", (PYTHON_PROC*)&py3_PyCapsule_GetPointer},
|
{"PyCapsule_GetPointer", (PYTHON_PROC*)&py3_PyCapsule_GetPointer},
|
||||||
@@ -638,7 +647,7 @@ static int py3initialised = 0;
|
|||||||
if (bytes != NULL) \
|
if (bytes != NULL) \
|
||||||
Py_XDECREF(bytes);
|
Py_XDECREF(bytes);
|
||||||
|
|
||||||
#define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self);
|
#define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self)
|
||||||
|
|
||||||
#define WIN_PYTHON_REF(win) win->w_python3_ref
|
#define WIN_PYTHON_REF(win) win->w_python3_ref
|
||||||
#define BUF_PYTHON_REF(buf) buf->b_python3_ref
|
#define BUF_PYTHON_REF(buf) buf->b_python3_ref
|
||||||
|
@@ -728,6 +728,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
998,
|
||||||
/**/
|
/**/
|
||||||
997,
|
997,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user