]> granicus.if.org Git - python/commitdiff
Patch #1380952: fix SSL objects timing out on consecutive read()s
authorGeorg Brandl <georg@python.org>
Fri, 31 Mar 2006 18:01:16 +0000 (18:01 +0000)
committerGeorg Brandl <georg@python.org>
Fri, 31 Mar 2006 18:01:16 +0000 (18:01 +0000)
Lib/test/test_socket_ssl.py
Misc/NEWS
Modules/_ssl.c

index 98680b92360275cb68bf2856005bc626fa9720a9..91a821295c7dfe5da08c685e33c6a342bbc672f5 100644 (file)
@@ -26,6 +26,19 @@ def test_basic():
     buf = f.read()
     f.close()
 
+def test_timeout():
+    test_support.requires('network')
+
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.settimeout(30.0)
+    # connect to service which issues an welcome banner (without need to write anything)
+    s.connect(("gmail.org", 995))
+    ss = socket.ssl(s)
+    # read part of return welcome banner twice,# read part of return welcome banner twice
+    ss.read(1)
+    ss.read(1)
+    s.close()
+                                           
 def test_rude_shutdown():
     try:
         import threading
@@ -74,6 +87,7 @@ def test_main():
         raise test_support.TestSkipped("socket module has no ssl support")
     test_rude_shutdown()
     test_basic()
+    test_timeout()
 
 if __name__ == "__main__":
     test_main()
index 55357d8c2ab3c2e1ee1a9689767d67e7728604e4..dc98c7a52134a70ded15a356a658fbd70bbb2262 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -303,6 +303,8 @@ Core and builtins
 Extension Modules
 -----------------
 
+- Patch #1380952: fix SSL objects timing out on consecutive read()s
+
 - Patch #1309579: wait3 and wait4 were added to the posix module.
 
 - Patch #1231053: The audioop module now supports encoding/decoding of alaw.
index 5f541f5aba504853b852351cf36d51144fc9f38d..0c085a8874ccc95066cd2c37ab9953b3f97ababf 100644 (file)
@@ -474,15 +474,22 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
 
        if (!(buf = PyString_FromStringAndSize((char *) 0, len)))
                return NULL;
+       
+       /* first check if there are bytes ready to be read */
+       Py_BEGIN_ALLOW_THREADS
+       count = SSL_pending(self->ssl);
+       Py_END_ALLOW_THREADS
 
-       sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
-       if (sockstate == SOCKET_HAS_TIMED_OUT) {
-               PyErr_SetString(PySSLErrorObject, "The read operation timed out");
-               Py_DECREF(buf);
-               return NULL;
-       } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
-               PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
-               return NULL;
+       if (!count) {
+               sockstate = check_socket_and_wait_for_timeout(self->Socket, 0);
+               if (sockstate == SOCKET_HAS_TIMED_OUT) {
+                       PyErr_SetString(PySSLErrorObject, "The read operation timed out");
+                       Py_DECREF(buf);
+                       return NULL;
+               } else if (sockstate == SOCKET_TOO_LARGE_FOR_SELECT) {
+                       PyErr_SetString(PySSLErrorObject, "Underlying socket too large for select().");
+                       return NULL;
+               }
        }
        do {
                err = 0;