diff options
author | Guido van Rossum <guido@python.org> | 2007-12-06 18:39:46 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-12-06 18:39:46 (GMT) |
commit | 03b5c9ae7587cfac1c1b6be22ee5d2f7f854d68b (patch) | |
tree | 6c5c05a61cfd11b45fa7de1b0c9c2153d71aeb4c /Modules/_ssl.c | |
parent | 4b28041530ce2dc8f741d544b6f86627348de3ef (diff) | |
download | cpython-03b5c9ae7587cfac1c1b6be22ee5d2f7f854d68b.zip cpython-03b5c9ae7587cfac1c1b6be22ee5d2f7f854d68b.tar.gz cpython-03b5c9ae7587cfac1c1b6be22ee5d2f7f854d68b.tar.bz2 |
Fix the leaks in test_ssl. Issue 1469. Patch by Christian Heimes:
(a) added GC support to the PySSL object
(b) move the call to _real_close() from __del__ methods in Python to
PySSL_dealloc().
(c) remove those __del__ methods -- this makes SSL and socket objects GC'able.
Diffstat (limited to 'Modules/_ssl.c')
-rw-r--r-- | Modules/_ssl.c | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index bd3f172..1aedaf8 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -266,7 +266,7 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, int ret; int verification_mode; - self = PyObject_New(PySSLObject, &PySSL_Type); /* Create new object */ + self = PyObject_GC_New(PySSLObject, &PySSL_Type); /* Create new object */ if (self == NULL) return NULL; self->peer_cert = NULL; @@ -385,6 +385,7 @@ newPySSLObject(PySocketSockObject *Sock, char *key_file, char *cert_file, self->Socket = Sock; Py_INCREF(self->Socket); + _PyObject_GC_TRACK(self); return self; fail: if (errstr) @@ -1050,16 +1051,41 @@ static PyObject *PySSL_cipher (PySSLObject *self) { return NULL; } -static void PySSL_dealloc(PySSLObject *self) +/* GC support. */ +static int +PySSL_traverse(PySSLObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->Socket); + return 0; +} + +static int +PySSL_clear(PySSLObject *self) +{ + Py_CLEAR(self->Socket); + return 0; +} + +static void +PySSL_dealloc(PySSLObject *self) { + PyObject *o; + PyObject *exc_type, *exc_value, *exc_tb; + + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + o = PyObject_CallMethod((PyObject*)self, "_real_close", NULL); + Py_XDECREF(o); + PyErr_Restore(exc_type, exc_value, exc_tb); + + PyObject_GC_UnTrack(self); if (self->peer_cert) /* Possible not to have one? */ - X509_free (self->peer_cert); + X509_free(self->peer_cert); if (self->ssl) SSL_free(self->ssl); if (self->ctx) SSL_CTX_free(self->ctx); - Py_XDECREF(self->Socket); - PyObject_Del(self); + Py_CLEAR(self->Socket); + Py_Type(self)->tp_free((PyObject *)self); } /* If the socket has a timeout, do a select()/poll() on the socket. @@ -1359,20 +1385,15 @@ static PyMethodDef PySSLMethods[] = { {NULL, NULL} }; -static PyObject *PySSL_getattr(PySSLObject *self, char *name) -{ - return Py_FindMethod(PySSLMethods, (PyObject *)self, name); -} - static PyTypeObject PySSL_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "ssl.SSLContext", /*tp_name*/ + "_ssl.SSLContext", /*tp_name*/ sizeof(PySSLObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)PySSL_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ - (getattrfunc)PySSL_getattr, /*tp_getattr*/ + 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ @@ -1380,6 +1401,32 @@ static PyTypeObject PySSL_Type = { 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)PySSL_traverse, /* tp_traverse */ + (inquiry)PySSL_clear, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + PySSLMethods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + PyObject_GC_Del, /* tp_free */ }; #ifdef HAVE_OPENSSL_RAND |