1 """Issue #143 - Socket timeouts in wsgi server not caught.
2 https://bitbucket.org/eventlet/eventlet/issue/143/
4 This file intentionally ignored by nose.
5 Caller process (tests.wsgi_test.TestWsgiConnTimeout) handles success / failure
8 Simulate server connection socket timeout without actually waiting.
9 Logs 'timed out' if server debug=True (similar to 'accepted' logging)
11 FAIL: if log (ie, _spawn_n_impl 'except:' catches timeout, logs TB)
12 NOTE: timeouts are NOT on server_sock, but on the conn sockets produced
13 by the socket.accept() call
15 server's socket.listen() sock - NaughtySocketAcceptWrap
19 server / client accept() conn - ExplodingConnectionWrap
23 connection makefile() file objects - ExplodingSocketFile <-- these raise
25 from __future__ import print_function
32 import tests.wsgi_test
35 # no standard tests in this file, ignore
39 # This test might make you wince
40 class NaughtySocketAcceptWrap(object):
41 # server's socket.accept(); patches resulting connection sockets
43 def __init__(self, sock):
45 self.sock._really_accept = self.sock.accept
46 self.sock.accept = self
50 self.sock.accept = self.sock._really_accept
51 del self.sock._really_accept
52 for conn_wrap in self.conn_reg:
57 for i in self.conn_reg:
61 print(self.__class__.__name__ + ".__call__")
62 conn, addr = self.sock._really_accept()
63 self.conn_reg.append(ExplodingConnectionWrap(conn))
67 class ExplodingConnectionWrap(object):
68 # new connection's socket.makefile
69 # eventlet *tends* to use socket.makefile, not raw socket methods.
70 # need to patch file operations
72 def __init__(self, conn):
74 self.conn._really_makefile = self.conn.makefile
75 self.conn.makefile = self
80 self.conn.makefile = self.conn._really_makefile
81 del self.conn._really_makefile
85 for i in self.file_reg:
88 def __call__(self, mode='r', bufsize=-1):
89 print(self.__class__.__name__ + ".__call__")
90 # file_obj = self.conn._really_makefile(*args, **kwargs)
91 file_obj = ExplodingSocketFile(self.conn._sock, mode, bufsize)
92 self.file_reg.append(file_obj)
96 class ExplodingSocketFile(eventlet.greenio._fileobject):
98 def __init__(self, sock, mode='rb', bufsize=-1, close=False):
99 super(self.__class__, self).__init__(sock, mode, bufsize, close)
108 print("=== ~* BOOM *~ ===")
109 raise socket.timeout("timed out")
111 def readline(self, *args, **kwargs):
112 print(self.__class__.__name__ + ".readline")
114 return super(self.__class__, self).readline(*args, **kwargs)
117 if __name__ == '__main__':
118 for debug in (False, True):
119 print("SEPERATOR_SENTINEL")
120 print("debug set to: %s" % debug)
122 server_sock = eventlet.listen(('localhost', 0))
123 server_addr = server_sock.getsockname()
124 sock_wrap = NaughtySocketAcceptWrap(server_sock)
127 eventlet.wsgi.server,
131 site=tests.wsgi_test.Site(),
137 sock1 = eventlet.connect(server_addr)
138 sock1.settimeout(0.1)
139 fd1 = sock1.makefile('rwb')
140 fd1.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
142 tests.wsgi_test.read_http(sock1)
144 # let the server socket ops catch up, set bomb
149 # req #2 - old conn, post-arm - timeout
150 fd1.write(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
153 tests.wsgi_test.read_http(sock1)
154 assert False, 'Expected ConnectionClosed exception'
155 except tests.wsgi_test.ConnectionClosed:
161 # reset streams, then output trapped tracebacks
163 # check output asserts in tests.wsgi_test.TestHttpd
164 # test_143_server_connection_timeout_exception