def test_close_with_makefile(self): def accept_close_early(listener): # verify that the makefile and the socket are truly independent # by closing the socket prior to using the made file try: conn, _ = listener.accept() fd = conn.makefile(mode='wb') conn.close() fd.write(b'hello\n') fd.close() _write_to_closed(fd, b'a') self.assertRaises(socket.error, conn.send, b'b') finally: listener.close() def accept_close_late(listener): # verify that the makefile and the socket are truly independent # by closing the made file and then sending a character try: conn, _ = listener.accept() fd = conn.makefile(mode='wb') fd.write(b'hello') fd.close() conn.send(b'\n') conn.close() _write_to_closed(fd, b'a') self.assertRaises(socket.error, conn.send, b'b') finally: listener.close() def did_it_work(server): client = socket.create_connection((params.DEFAULT_CONNECT, server.getsockname()[1])) fd = client.makefile(mode='rb') client.close() self.assertEqual(fd.readline(), b'hello\n') self.assertFalse(fd.read()) fd.close() server = tcp_listener() server_greenlet = gevent.spawn(accept_close_early, server) did_it_work(server) server_greenlet.kill() server = tcp_listener() server_greenlet = gevent.spawn(accept_close_late, server) did_it_work(server) server_greenlet.kill()
def test_del_closes_socket(self): def accept_once(listener): # delete/overwrite the original conn # object, only keeping the file object around # closing the file object should close everything # XXX: This is not exactly true on Python 3. # This produces a ResourceWarning. oconn = None try: conn, _ = listener.accept() if PY3: oconn = conn conn = conn.makefile(mode='wb') conn.write(b'hello\n') conn.close() _write_to_closed(conn, b'a') finally: listener.close() if oconn is not None: oconn.close() server = tcp_listener() gevent.spawn(accept_once, server) client = socket.create_connection((params.DEFAULT_CONNECT, server.getsockname()[1])) with gevent.Timeout.start_new(0.5): fd = client.makefile() client.close() self.assertEqual(fd.read(), 'hello\n') self.assertEqual(fd.read(), '')
def test_del_closes_socket(self): import warnings def accept_once(listener): # delete/overwrite the original conn # object, only keeping the file object around # closing the file object should close everything # This is not *exactly* true on Python 3. This produces # a ResourceWarning, which we silence below. (Previously we actually # *saved* a reference to the socket object, so we # weren't testing what we thought we were.) # It's definitely not true on PyPy, which needs GC to # reliably close everything; sometimes this is more than # one collection cycle. And PyPy issues a warning with -X # track-resources that we cannot catch. with warnings.catch_warnings(): warnings.simplefilter('ignore') try: conn = listener.accept()[0] # Note that we overwrite the original variable, # losing our reference to the socket. conn = conn.makefile(mode='wb') conn.write(b'hello\n') conn.close() _write_to_closed(conn, b'a') finally: listener.close() del listener del conn gc_collect_if_needed() gc_collect_if_needed() server = tcp_listener() gevent.spawn(accept_once, server) client = socket.create_connection((params.DEFAULT_CONNECT, server.getsockname()[1])) with gevent.Timeout.start_new(0.5): fd = client.makefile() client.close() self.assertEqual(fd.read(), 'hello\n') # If the socket isn't closed when 'accept_once' finished, # then this will hang and exceed the timeout self.assertEqual(fd.read(), '') fd.close() del client del fd
def setUp(self): super(Test, self).setUp() self.server = self._close_on_teardown(greentest.tcp_listener(backlog=1)) self.server_port = self.server.getsockname()[1] self.acceptor = gevent.spawn(self._accept) gevent.sleep(0)