From: Jeremy Hylton Date: Fri, 9 May 2003 18:29:21 +0000 (+0000) Subject: Backport fixes to make more types collectable. X-Git-Tag: v2.2.3c1~40 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d8136b500a73eb48ba2e122c3f8e0fb858218c9e;p=thirdparty%2FPython%2Fcpython.git Backport fixes to make more types collectable. classmethod, staticmethod, cPickle.Pickler, cPickle.UNpickler --- diff --git a/Misc/NEWS b/Misc/NEWS index e8a165486a51..29add1047454 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -88,6 +88,9 @@ Release date: XX-XXX-2003 - Fixed sundry memory leaks. +- More objects participate in garbage collection: classmethod, + staticmethod, and cPickle Pickler and Unpickler. (SF #735247) + - Improve the robustness of the methods for random distributions so they can work with generators producing a full range of values (unlike the Wichmann-Hill generator which never produces a zero). diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 214dc62ccd4f..5ecf744ff818 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -1,51 +1,3 @@ -/* - * cPickle.c,v 1.71 1999/07/11 13:30:34 jim Exp - * - * Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * o Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the disclaimer that follows. - * - * o Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions, and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * o Neither the name of Digital Creations nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * - * THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS - * IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL - * CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - # - # If you have questions regarding this software, contact: - # - # Digital Creations, L.C. - # 910 Princess Ann Street - # Fredericksburge, Virginia 22401 - # - # info@digicool.com - # - # (540) 371-6909 - */ - static char cPickle_module_documentation[] = "C implementation and optimization of the Python pickle module\n" "\n" @@ -2302,7 +2254,7 @@ static Picklerobject * newPicklerobject(PyObject *file, int bin) { Picklerobject *self; - UNLESS (self = PyObject_New(Picklerobject, &Picklertype)) + UNLESS (self = PyObject_GC_New(Picklerobject, &Picklertype)) return NULL; self->fp = NULL; @@ -2403,6 +2355,7 @@ get_Pickler(PyObject *self, PyObject *args) { static void Pickler_dealloc(Picklerobject *self) { + PyObject_GC_UnTrack(self); Py_XDECREF(self->write); Py_XDECREF(self->memo); Py_XDECREF(self->fast_memo); @@ -2416,7 +2369,45 @@ Pickler_dealloc(Picklerobject *self) { free(self->write_buf); } - PyObject_Del(self); + PyObject_GC_Del(self); +} + +static int +Pickler_traverse(Picklerobject *self, visitproc visit, void *arg) +{ + int err; +#define VISIT(SLOT) \ + if (SLOT) { \ + err = visit((PyObject *)(SLOT), arg); \ + if (err) \ + return err; \ + } + VISIT(self->write); + VISIT(self->memo); + VISIT(self->fast_memo); + VISIT(self->arg); + VISIT(self->file); + VISIT(self->pers_func); + VISIT(self->inst_pers_func); + VISIT(self->dispatch_table); +#undef VISIT + return 0; +} + +static int +Pickler_clear(Picklerobject *self) +{ +#define CLEAR(SLOT) Py_XDECREF(SLOT); SLOT = NULL; + CLEAR(self->write); + CLEAR(self->memo); + CLEAR(self->fast_memo); + CLEAR(self->arg); + CLEAR(self->file); + CLEAR(self->pers_func); + CLEAR(self->inst_pers_func); + CLEAR(self->dispatch_table); +#undef CLEAR + return 0; } static PyObject * @@ -2532,10 +2523,10 @@ static PyTypeObject Picklertype = { 0, /* set below */ /* tp_getattro */ 0, /* set below */ /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, Picklertype__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)Pickler_traverse, /* tp_traverse */ + (inquiry)Pickler_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -4221,7 +4212,7 @@ static Unpicklerobject * newUnpicklerobject(PyObject *f) { Unpicklerobject *self; - UNLESS (self = PyObject_New(Unpicklerobject, &Unpicklertype)) + UNLESS (self = PyObject_GC_New(Unpicklerobject, &Unpicklertype)) return NULL; self->file = NULL; @@ -4308,6 +4299,7 @@ get_Unpickler(PyObject *self, PyObject *args) { static void Unpickler_dealloc(Unpicklerobject *self) { + PyObject_GC_UnTrack((PyObject *)self); Py_XDECREF(self->readline); Py_XDECREF(self->read); Py_XDECREF(self->file); @@ -4326,9 +4318,47 @@ Unpickler_dealloc(Unpicklerobject *self) { free(self->buf); } - PyObject_Del(self); + PyObject_GC_Del(self); } +static int +Unpickler_traverse(Unpicklerobject *self, visitproc visit, void *arg) +{ + int err; + +#define VISIT(SLOT) \ + if (SLOT) { \ + err = visit((PyObject *)(SLOT), arg); \ + if (err) \ + return err; \ + } + VISIT(self->readline); + VISIT(self->read); + VISIT(self->file); + VISIT(self->memo); + VISIT(self->stack); + VISIT(self->pers_func); + VISIT(self->arg); + VISIT(self->last_string); +#undef VISIT + return 0; +} + +static int +Unpickler_clear(Unpicklerobject *self) +{ +#define CLEAR(SLOT) Py_XDECREF(SLOT); SLOT = NULL + CLEAR(self->readline); + CLEAR(self->read); + CLEAR(self->file); + CLEAR(self->memo); + CLEAR(self->stack); + CLEAR(self->pers_func); + CLEAR(self->arg); + CLEAR(self->last_string); +#undef CLEAR + return 0; +} static PyObject * Unpickler_getattr(Unpicklerobject *self, char *name) { @@ -4512,27 +4542,29 @@ static char Unpicklertype__doc__[] = static PyTypeObject Unpicklertype = { PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "cPickle.Unpickler", /*tp_name*/ - sizeof(Unpicklerobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)Unpickler_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - (getattrfunc)Unpickler_getattr, /*tp_getattr*/ - (setattrfunc)Unpickler_setattr, /*tp_setattr*/ - (cmpfunc)0, /*tp_compare*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - - /* Space for future expansion */ - 0L,0L,0L,0L, - Unpicklertype__doc__ /* Documentation string */ + 0, /*ob_size*/ + "cPickle.Unpickler", /*tp_name*/ + sizeof(Unpicklerobject), /*tp_basicsize*/ + 0, + (destructor)Unpickler_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)Unpickler_getattr, /* tp_getattr */ + (setattrfunc)Unpickler_setattr, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + Unpicklertype__doc__, /* tp_doc */ + (traverseproc)Unpickler_traverse, /* tp_traverse */ + (inquiry)Unpickler_clear, /* tp_clear */ }; static struct PyMethodDef cPickle_methods[] = { diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 426b8f490a44..e05a93afd647 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -460,10 +460,28 @@ typedef struct { static void cm_dealloc(classmethod *cm) { + _PyObject_GC_UNTRACK((PyObject *)cm); Py_XDECREF(cm->cm_callable); cm->ob_type->tp_free((PyObject *)cm); } +static int +cm_traverse(classmethod *cm, visitproc visit, void *arg) +{ + if (!cm->cm_callable) + return 0; + return visit(cm->cm_callable, arg); +} + +static int +cm_clear(classmethod *cm) +{ + Py_XDECREF(cm->cm_callable); + cm->cm_callable = NULL; + + return 0; +} + static PyObject * cm_descr_get(PyObject *self, PyObject *obj, PyObject *type) { @@ -535,10 +553,10 @@ PyTypeObject PyClassMethod_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, classmethod_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)cm_traverse, /* tp_traverse */ + (inquiry)cm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -554,7 +572,7 @@ PyTypeObject PyClassMethod_Type = { cm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - _PyObject_Del, /* tp_free */ + _PyObject_GC_Del, /* tp_free */ }; PyObject * @@ -594,10 +612,28 @@ typedef struct { static void sm_dealloc(staticmethod *sm) { + _PyObject_GC_UNTRACK((PyObject *)sm); Py_XDECREF(sm->sm_callable); sm->ob_type->tp_free((PyObject *)sm); } +static int +sm_traverse(staticmethod *sm, visitproc visit, void *arg) +{ + if (!sm->sm_callable) + return 0; + return visit(sm->sm_callable, arg); +} + +static int +sm_clear(staticmethod *sm) +{ + Py_XDECREF(sm->sm_callable); + sm->sm_callable = NULL; + + return 0; +} + static PyObject * sm_descr_get(PyObject *self, PyObject *obj, PyObject *type) { @@ -664,10 +700,10 @@ PyTypeObject PyStaticMethod_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, staticmethod_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ + (traverseproc)sm_traverse, /* tp_traverse */ + (inquiry)sm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -683,7 +719,7 @@ PyTypeObject PyStaticMethod_Type = { sm_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - _PyObject_Del, /* tp_free */ + _PyObject_GC_Del, /* tp_free */ }; PyObject *