From 43f08a85e4b86acf6e4313a51cec4df0cc586da7 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 31 Mar 2006 18:01:16 +0000 Subject: [PATCH] Patch #1380952: fix SSL objects timing out on consecutive read()s --- Lib/test/test_socket_ssl.py | 14 ++++++++++++++ Misc/NEWS | 2 ++ Modules/_ssl.c | 23 +++++++++++++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_socket_ssl.py b/Lib/test/test_socket_ssl.py index 98680b92360..91a821295c7 100644 --- a/Lib/test/test_socket_ssl.py +++ b/Lib/test/test_socket_ssl.py @@ -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() diff --git a/Misc/NEWS b/Misc/NEWS index 55357d8c2ab..dc98c7a5213 100644 --- 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. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 5f541f5aba5..0c085a8874c 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -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;