From c8418a10e4c750e7df6bc036d872f1395d21cc24 Mon Sep 17 00:00:00 2001 From: Sergey Shepelev Date: Fri, 11 Jan 2013 17:00:37 +0400 Subject: [PATCH] tests: ssl: socket.sendall() busy loop when client is reading slowly https://bitbucket.org/which_linden/eventlet/issue/134 --- tests/ssl_test.py | 63 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/tests/ssl_test.py b/tests/ssl_test.py index eb7dbeb..34d7fce 100644 --- a/tests/ssl_test.py +++ b/tests/ssl_test.py @@ -1,10 +1,10 @@ -from tests import LimitedTestCase, certificate_file, private_key_file +from tests import LimitedTestCase, certificate_file, private_key_file, check_idle_cpu_usage from tests import skip_if_no_ssl from unittest import main import eventlet -from eventlet import util, coros, greenio +from eventlet import util, greenio import socket -import os + def listen_ssl_socket(address=('127.0.0.1', 0)): sock = util.wrap_ssl(socket.socket(), certificate_file, @@ -13,7 +13,7 @@ def listen_ssl_socket(address=('127.0.0.1', 0)): sock.listen(50) return sock - + class SSLTest(LimitedTestCase): @skip_if_no_ssl @@ -26,12 +26,12 @@ class SSLTest(LimitedTestCase): sock = listen_ssl_socket() server_coro = eventlet.spawn(serve, sock) - + client = util.wrap_ssl(eventlet.connect(('127.0.0.1', sock.getsockname()[1]))) client.write('line 1\r\nline 2\r\n\r\n') self.assertEquals(client.read(8192), 'response') server_coro.wait() - + @skip_if_no_ssl def test_ssl_close(self): def serve(listener): @@ -41,18 +41,18 @@ class SSLTest(LimitedTestCase): self.assertEquals("", sock.read(8192)) except greenio.SSL.ZeroReturnError: pass - + sock = listen_ssl_socket() server_coro = eventlet.spawn(serve, sock) - + raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1])) client = util.wrap_ssl(raw_client) client.write('X') greenio.shutdown_safe(client) client.close() server_coro.wait() - + @skip_if_no_ssl def test_ssl_connect(self): def serve(listener): @@ -60,7 +60,7 @@ class SSLTest(LimitedTestCase): stuff = sock.read(8192) sock = listen_ssl_socket() server_coro = eventlet.spawn(serve, sock) - + raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ssl_client = util.wrap_ssl(raw_client) ssl_client.connect(('127.0.0.1', sock.getsockname()[1])) @@ -93,6 +93,47 @@ class SSLTest(LimitedTestCase): client2.send('after') server_coro.wait() + @skip_if_no_ssl + def test_sendall_cpu_usage(self): + """SSL socket.sendall() busy loop + + https://bitbucket.org/which_linden/eventlet/issue/134/greenssl-performance-issues + + Idea of this test is to check that GreenSSLSocket.sendall() does not busy loop + retrying .send() calls, but instead trampolines until socket is writeable. + + BUFFER_SIZE and SENDALL_SIZE are magic numbers inferred through trial and error. + """ + # Time limit resistant to busy loops + self.set_alarm(1) + + stage_1 = eventlet.event.Event() + BUFFER_SIZE = 1000 + SENDALL_SIZE = 100000 + + def serve(listener): + conn, _ = listener.accept() + conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, BUFFER_SIZE) + self.assertEqual(conn.read(8), 'request') + conn.write('response') + + stage_1.wait() + conn.sendall('x' * SENDALL_SIZE) + + server_sock = listen_ssl_socket() + server_coro = eventlet.spawn(serve, server_sock) + + client_sock = eventlet.connect(server_sock.getsockname()) + client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFER_SIZE) + client = util.wrap_ssl(client_sock) + client.write('request') + self.assertEqual(client.read(8), 'response') + stage_1.send() + + check_idle_cpu_usage(0.2, 0.1) + server_coro.kill() + + class SocketSSLTest(LimitedTestCase): @skip_if_no_ssl def test_greensslobject(self): @@ -114,6 +155,6 @@ class SocketSSLTest(LimitedTestCase): self.assertEquals(client.read(1024), 'content') self.assertEquals(client.read(1024), '') - + if __name__ == '__main__': main()