简体   繁体   中英

asyncio Transport does not close TCP connection

So I'm having a bit of a problem with asyncio. Reference code is:

In summary:

Time out is set like so :

    def _reset_timeout(self, duration=None):
        if self._timeout_handle is not None:
            self._timeout_handle.cancel()
        self._timeout_handle = self.loop.call_later(
            duration or self._timeout_duration, self._timeout_cb
        )

self._timeout_cb is like so:

    def _timeout_cb(self):
        log.info('%r connection timeout', self.session.peer)
        self.transport.close()

_reset_timeout is invoked in this part , like so:

            self._reset_timeout(self._proxy_timeout)

The test is like so:

class TestProxyProtocolV1Controller:
    def test_timeout(self, plain_controller):
        # The next line ensures that _proxy_timeout is set
        assert plain_controller.smtpd._proxy_timeout > 0.0
        prox_test = b"PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect(Global.SrvAddr)
            # The next line simulates timeout
            time.sleep(plain_controller.smtpd._proxy_timeout * 1.1)
            with pytest.raises(ConnectionAbortedError):
                sock.send(prox_test)
                _ = sock.recv(4096)

This test works on Windows, but fails in Linux . The failure is like so:

aiosmtpd/tests/test_proxyprotocol.py:632: in test_timeout
    _ = sock.recv(4096)
E   Failed: DID NOT RAISE <class 'ConnectionAbortedError'>

If I remove the pytest.raises part in the test, it works in Linux... but that means timeout is not ending the connection, and that is incorrect!

So, in essence, my thought is:

self.transport.close() ended the TCP connection in Windows, but somehow kept TCP connection alive in Linux.

How do I make TCP connection ends on Linux? What else should I do besides self.transport.close() ?

I decided to post my workaround that I implemented.

So, instead of mucking inside the server code, I edited the test case like so:

class TestProxyProtocolV1Controller:
    def test_timeout(self, plain_controller):
        # The next line ensures that _proxy_timeout is set
        assert plain_controller.smtpd._proxy_timeout > 0.0
        prox_test = b"PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect(Global.SrvAddr)
            # The next line simulates timeout
            time.sleep(plain_controller.smtpd._proxy_timeout * 1.1)
            with pytest.raises(ConnectionAbortedError):
                sock.send(prox_test)
                resp = sock.recv(4096)
                if resp == b"":
                    raise ConnectionAbortedError

I'm totally not happy with this, so I'd appreciate any suggestions/corrections.

But in any case, the development can at least continue for the time being.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM