Update context.c to use the thread state management macros unconditionally, since conn->tstate is always NULL now
diff --git a/leakcheck/context-verify-callback.py b/leakcheck/context-verify-callback.py
new file mode 100644
index 0000000..5e49d7a
--- /dev/null
+++ b/leakcheck/context-verify-callback.py
@@ -0,0 +1,98 @@
+# Copyright (C) Jean-Paul Calderone 2008, All rights reserved
+#
+# Stress tester for thread-related bugs in global_verify_callback in
+# src/ssl/context.c.  This will reliably segfault if context.c isn't a
+# PyThreadState management technique which is compatible with the approach used
+# by ssl.c.
+
+
+from itertools import count
+from threading import Thread
+from socket import socket
+
+from OpenSSL.SSL import Context, TLSv1_METHOD, VERIFY_PEER, Connection, WantReadError
+from OpenSSL.crypto import FILETYPE_PEM, load_certificate, load_privatekey
+
+cleartextPrivateKeyPEM = (
+    "-----BEGIN RSA PRIVATE KEY-----\n"
+    "MIICXAIBAAKBgQDaemNe1syksAbFFpF3aoOrZ18vB/IQNZrAjFqXPv9iieJm7+Tc\n"
+    "g+lA/v0qmoEKrpT2xfwxXmvZwBNM4ZhyRC3DPIFEyJV7/3IA1p5iuMY/GJI1VIgn\n"
+    "aikQCnrsyxtaRpsMBeZRniaVzcUJ+XnEdFGEjlo+k0xlwfVclDEMwgpXAQIDAQAB\n"
+    "AoGBALi0a7pMQqqgnriVAdpBVJveQtxSDVWi2/gZMKVZfzNheuSnv4amhtaKPKJ+\n"
+    "CMZtHkcazsE2IFvxRN/kgato9H3gJqq8nq2CkdpdLNVKBoxiCtkLfutdY4SQLtoY\n"
+    "USN7exk131pchsAJXYlR6mCW+ZP+E523cNwpPgsyKxVbmXSBAkEA9470fy2W0jFM\n"
+    "taZFslpntKSzbvn6JmdtjtvWrM1bBaeeqFiGBuQFYg46VaCUaeRWYw02jmYAsDYh\n"
+    "ZQavmXThaQJBAOHtlAQ0IJJEiMZr6vtVPH32fmbthSv1AUSYPzKqdlQrUnOXPQXu\n"
+    "z70cFoLG1TvPF5rBxbOkbQ/s8/ka5ZjPfdkCQCeC7YsO36+UpsWnUCBzRXITh4AC\n"
+    "7eYLQ/U1KUJTVF/GrQ/5cQrQgftwgecAxi9Qfmk4xqhbp2h4e0QAmS5I9WECQH02\n"
+    "0QwrX8nxFeTytr8pFGezj4a4KVCdb2B3CL+p3f70K7RIo9d/7b6frJI6ZL/LHQf2\n"
+    "UP4pKRDkgKsVDx7MELECQGm072/Z7vmb03h/uE95IYJOgY4nfmYs0QKA9Is18wUz\n"
+    "DpjfE33p0Ha6GO1VZRIQoqE24F8o5oimy3BEjryFuw4=\n"
+    "-----END RSA PRIVATE KEY-----\n")
+
+
+cleartextCertificatePEM = (
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICfTCCAeYCAQEwDQYJKoZIhvcNAQEEBQAwgYYxCzAJBgNVBAYTAlVTMRkwFwYD\n"
+    "VQQDExBweW9wZW5zc2wuc2YubmV0MREwDwYDVQQHEwhOZXcgWW9yazESMBAGA1UE\n"
+    "ChMJUHlPcGVuU1NMMREwDwYDVQQIEwhOZXcgWW9yazEQMA4GCSqGSIb3DQEJARYB\n"
+    "IDEQMA4GA1UECxMHVGVzdGluZzAeFw0wODAzMjUxOTA0MTNaFw0wOTAzMjUxOTA0\n"
+    "MTNaMIGGMQswCQYDVQQGEwJVUzEZMBcGA1UEAxMQcHlvcGVuc3NsLnNmLm5ldDER\n"
+    "MA8GA1UEBxMITmV3IFlvcmsxEjAQBgNVBAoTCVB5T3BlblNTTDERMA8GA1UECBMI\n"
+    "TmV3IFlvcmsxEDAOBgkqhkiG9w0BCQEWASAxEDAOBgNVBAsTB1Rlc3RpbmcwgZ8w\n"
+    "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANp6Y17WzKSwBsUWkXdqg6tnXy8H8hA1\n"
+    "msCMWpc+/2KJ4mbv5NyD6UD+/SqagQqulPbF/DFea9nAE0zhmHJELcM8gUTIlXv/\n"
+    "cgDWnmK4xj8YkjVUiCdqKRAKeuzLG1pGmwwF5lGeJpXNxQn5ecR0UYSOWj6TTGXB\n"
+    "9VyUMQzCClcBAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAmm0Vzvv1O91WLl2LnF2P\n"
+    "q55LJdOnJbCCXIgxLdoVmvYAz1ZJq1eGKgKWI5QLgxiSzJLEU7KK//aVfiZzoCd5\n"
+    "RipBiEEMEV4eAY317bHPwPP+4Bj9t0l8AsDLseC5vLRHgxrLEu3bn08DYx6imB5Q\n"
+    "UBj849/xpszEM7BhwKE0GiQ=\n"
+    "-----END CERTIFICATE-----\n")
+
+count = count()
+def go():
+    port = socket()
+    port.bind(('', 0))
+    port.listen(1)
+
+    called = []
+    def info(*args):
+        print count.next()
+        called.append(None)
+        return 1
+    context = Context(TLSv1_METHOD)
+    context.set_verify(VERIFY_PEER, info)
+    context.use_certificate(
+        load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
+    context.use_privatekey(
+        load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
+
+    while 1:
+        client = socket()
+        client.setblocking(False)
+        client.connect_ex(port.getsockname())
+
+        clientSSL = Connection(context, client)
+        clientSSL.set_connect_state()
+
+        server, ignored = port.accept()
+        server.setblocking(False)
+
+        serverSSL = Connection(context, server)
+        serverSSL.set_accept_state()
+
+        del called[:]
+        while not called:
+            for ssl in clientSSL, serverSSL:
+                try:
+                    ssl.send('foo')
+                except WantReadError, e:
+                    pass
+
+
+threads = [Thread(target=go, args=()) for i in xrange(2)]
+for th in threads:
+    th.start()
+for th in threads:
+    th.join()
+