tests: ssl: socket.sendall() busy loop when client is reading slowly
https://bitbucket.org/which_linden/eventlet/issue/134
This commit is contained in:
@@ -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 tests import skip_if_no_ssl
|
||||||
from unittest import main
|
from unittest import main
|
||||||
import eventlet
|
import eventlet
|
||||||
from eventlet import util, coros, greenio
|
from eventlet import util, greenio
|
||||||
import socket
|
import socket
|
||||||
import os
|
|
||||||
|
|
||||||
def listen_ssl_socket(address=('127.0.0.1', 0)):
|
def listen_ssl_socket(address=('127.0.0.1', 0)):
|
||||||
sock = util.wrap_ssl(socket.socket(), certificate_file,
|
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)
|
sock.listen(50)
|
||||||
|
|
||||||
return sock
|
return sock
|
||||||
|
|
||||||
|
|
||||||
class SSLTest(LimitedTestCase):
|
class SSLTest(LimitedTestCase):
|
||||||
@skip_if_no_ssl
|
@skip_if_no_ssl
|
||||||
@@ -26,12 +26,12 @@ class SSLTest(LimitedTestCase):
|
|||||||
sock = listen_ssl_socket()
|
sock = listen_ssl_socket()
|
||||||
|
|
||||||
server_coro = eventlet.spawn(serve, sock)
|
server_coro = eventlet.spawn(serve, sock)
|
||||||
|
|
||||||
client = util.wrap_ssl(eventlet.connect(('127.0.0.1', sock.getsockname()[1])))
|
client = util.wrap_ssl(eventlet.connect(('127.0.0.1', sock.getsockname()[1])))
|
||||||
client.write('line 1\r\nline 2\r\n\r\n')
|
client.write('line 1\r\nline 2\r\n\r\n')
|
||||||
self.assertEquals(client.read(8192), 'response')
|
self.assertEquals(client.read(8192), 'response')
|
||||||
server_coro.wait()
|
server_coro.wait()
|
||||||
|
|
||||||
@skip_if_no_ssl
|
@skip_if_no_ssl
|
||||||
def test_ssl_close(self):
|
def test_ssl_close(self):
|
||||||
def serve(listener):
|
def serve(listener):
|
||||||
@@ -41,18 +41,18 @@ class SSLTest(LimitedTestCase):
|
|||||||
self.assertEquals("", sock.read(8192))
|
self.assertEquals("", sock.read(8192))
|
||||||
except greenio.SSL.ZeroReturnError:
|
except greenio.SSL.ZeroReturnError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
sock = listen_ssl_socket()
|
sock = listen_ssl_socket()
|
||||||
|
|
||||||
server_coro = eventlet.spawn(serve, sock)
|
server_coro = eventlet.spawn(serve, sock)
|
||||||
|
|
||||||
raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1]))
|
raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1]))
|
||||||
client = util.wrap_ssl(raw_client)
|
client = util.wrap_ssl(raw_client)
|
||||||
client.write('X')
|
client.write('X')
|
||||||
greenio.shutdown_safe(client)
|
greenio.shutdown_safe(client)
|
||||||
client.close()
|
client.close()
|
||||||
server_coro.wait()
|
server_coro.wait()
|
||||||
|
|
||||||
@skip_if_no_ssl
|
@skip_if_no_ssl
|
||||||
def test_ssl_connect(self):
|
def test_ssl_connect(self):
|
||||||
def serve(listener):
|
def serve(listener):
|
||||||
@@ -60,7 +60,7 @@ class SSLTest(LimitedTestCase):
|
|||||||
stuff = sock.read(8192)
|
stuff = sock.read(8192)
|
||||||
sock = listen_ssl_socket()
|
sock = listen_ssl_socket()
|
||||||
server_coro = eventlet.spawn(serve, sock)
|
server_coro = eventlet.spawn(serve, sock)
|
||||||
|
|
||||||
raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
ssl_client = util.wrap_ssl(raw_client)
|
ssl_client = util.wrap_ssl(raw_client)
|
||||||
ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
|
ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
|
||||||
@@ -93,6 +93,47 @@ class SSLTest(LimitedTestCase):
|
|||||||
client2.send('after')
|
client2.send('after')
|
||||||
server_coro.wait()
|
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):
|
class SocketSSLTest(LimitedTestCase):
|
||||||
@skip_if_no_ssl
|
@skip_if_no_ssl
|
||||||
def test_greensslobject(self):
|
def test_greensslobject(self):
|
||||||
@@ -114,6 +155,6 @@ class SocketSSLTest(LimitedTestCase):
|
|||||||
self.assertEquals(client.read(1024), 'content')
|
self.assertEquals(client.read(1024), 'content')
|
||||||
self.assertEquals(client.read(1024), '')
|
self.assertEquals(client.read(1024), '')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user