You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by nl...@apache.org on 2004/12/19 20:36:38 UTC
svn commit: r122780 - /httpd/mod_python/trunk/src/requestobject.c
Author: nlehuen
Date: Sun Dec 19 11:36:36 2004
New Revision: 122780
URL: http://svn.apache.org/viewcvs?view=rev&rev=122780
Log:
Fix for bug #1 "circular references starting from the request object create a memory leak" : edited requestobject.c to add garbage collection support to the request object.
Modified:
httpd/mod_python/trunk/src/requestobject.c
Modified: httpd/mod_python/trunk/src/requestobject.c
Url: http://svn.apache.org/viewcvs/httpd/mod_python/trunk/src/requestobject.c?view=diff&rev=122780&p1=httpd/mod_python/trunk/src/requestobject.c&r1=122779&p2=httpd/mod_python/trunk/src/requestobject.c&r2=122780
==============================================================================
--- httpd/mod_python/trunk/src/requestobject.c (original)
+++ httpd/mod_python/trunk/src/requestobject.c Sun Dec 19 11:36:36 2004
@@ -36,7 +36,7 @@
{
requestobject *result;
- result = PyObject_New(requestobject, &MpRequest_Type);
+ result = PyObject_GC_New(requestobject, &MpRequest_Type);
if (! result)
return PyErr_NoMemory();
@@ -63,6 +63,11 @@
result->rbuff_pos = 0;
result->rbuff_len = 0;
+ // we make sure that the object dictionary is there
+ // before registering the object with the GC
+ _PyObject_GetDictPtr(result);
+ PyObject_GC_Track(result);
+
return (PyObject *) result;
}
@@ -1317,6 +1322,11 @@
static void request_dealloc(requestobject *self)
{
+ // de-register the object from the GC
+ // before its deallocation, to prevent the
+ // GC to run on a partially de-allocated object
+ PyObject_GC_UnTrack(self);
+
Py_XDECREF(self->dict);
Py_XDECREF(self->connection);
Py_XDECREF(self->server);
@@ -1331,7 +1341,48 @@
Py_XDECREF(self->phase);
Py_XDECREF(self->hlo);
- PyObject_Del(self);
+ PyObject_GC_Del(self);
+}
+
+/**
+ ** request_tp_traverse
+ **
+ * Traversal of the request object
+ */
+static int request_tp_traverse(PyObject *self, visitproc visit, void *arg) {
+ PyObject *dict,*values,*item,*str;
+ int i,size;
+
+ // only traverse its dictionary since other fields defined in request_rec_mbrs with type T_OBJECT
+ // cannot be the source of memory leaks (unless you really want it)
+ dict=*_PyObject_GetDictPtr(self);
+ if(dict) {
+ // this check is not needed, I guess, _PyObject_GetDictPtr always give a pointer to a dict object.
+ if(PyDict_Check(dict)) {
+ i = visit(dict,arg);
+ if(i) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ((requestobject*)self)->request_rec, "%s:%i Call to visit() failed",__LINE__,__FILE__);
+ // no need to Py_DECREF(dict) since the reference is borrowed
+ return i;
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ((requestobject*)self)->request_rec, "%s:%i Expected a dictionary",__LINE__,__FILE__);
+ }
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, ((requestobject*)self)->request_rec, "%s:%i Expected a dictionary",__LINE__,__FILE__);
+ }
+ // no need to Py_DECREF(dict) since the reference is borrowed
+ return 0;
+}
+
+static int request_tp_clear(PyObject *self) {
+ // No need to clear anything, as it is
+ // the object dictionary that will clear itself.
+ // Other fields defined in request_rec_mbrs with type T_OBJECT
+ // cannot be the source of memory leaks (unless you really want it)
+ return 0;
}
static char request_doc[] =
@@ -1359,10 +1410,11 @@
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Py_TPFLAGS_BASETYPE|
+ Py_TPFLAGS_HAVE_GC , /* tp_flags */
request_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
+ request_tp_traverse, /* tp_traverse */
+ request_tp_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */