[Python-3000-checkins] r59394 - in python/branches/py3k: Lib/ssl.py Modules/_ssl.c

guido.van.rossum python-3000-checkins at python.org
Thu Dec 6 19:39:47 CET 2007


Author: guido.van.rossum
Date: Thu Dec  6 19:39:46 2007
New Revision: 59394

Modified:
   python/branches/py3k/Lib/ssl.py
   python/branches/py3k/Modules/_ssl.c
Log:
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.


Modified: python/branches/py3k/Lib/ssl.py
==============================================================================
--- python/branches/py3k/Lib/ssl.py	(original)
+++ python/branches/py3k/Lib/ssl.py	Thu Dec  6 19:39:46 2007
@@ -148,6 +148,10 @@
         self.do_handshake_on_connect = do_handshake_on_connect
         self.suppress_ragged_eofs = suppress_ragged_eofs
 
+    # See Modules/_ssl.c:PySSL_dealloc()
+    # def __del__(self):
+    #    self._real_close()
+
     def dup(self):
         raise NotImplemented("Can't dup() %s instances" %
                              self.__class__.__name__)
@@ -300,6 +304,7 @@
         socket.shutdown(self, how)
 
     def _real_close(self):
+        # real close is called by Modules/_ssl.c:PySSL_dealloc()
         self._sslobj = None
         # self._closed = True
         if self._base:
@@ -348,10 +353,6 @@
                               self.do_handshake_on_connect),
                 addr)
 
-
-    def __del__(self):
-        self._real_close()
-
 def wrap_socket(sock, keyfile=None, certfile=None,
                 server_side=False, cert_reqs=CERT_NONE,
                 ssl_version=PROTOCOL_SSLv23, ca_certs=None,

Modified: python/branches/py3k/Modules/_ssl.c
==============================================================================
--- python/branches/py3k/Modules/_ssl.c	(original)
+++ python/branches/py3k/Modules/_ssl.c	Thu Dec  6 19:39:46 2007
@@ -266,7 +266,7 @@
 	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 @@
 
 	self->Socket = Sock;
 	Py_INCREF(self->Socket);
+	_PyObject_GC_TRACK(self);
 	return self;
  fail:
 	if (errstr)
@@ -1050,16 +1051,41 @@
 	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 @@
 	{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 @@
 	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


More information about the Python-3000-checkins mailing list