Skip to content

Commit

Permalink
Lingering close doesn't terminate before timeout #1559
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Kim committed Jan 26, 2017
1 parent 6902d3e commit 4a59c4f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
5 changes: 3 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ CHANGES

- Do not pause transport during set_parser stage #1211

- Fix typo in FAQ section "How to programmatically close websocket server-side?"
- Lingering close doesn't terminate before timeout #1559

- Allow users to specify what should happen to decoding errors when calling a responses `text()` method #1542
- Allow users to specify what should happen to decoding errors
when calling a responses `text()` method #1542


1.2.0 (2016-12-17)
Expand Down
21 changes: 13 additions & 8 deletions aiohttp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def __init__(self, *, loop=None,
max_line_size=8190,
max_headers=32768,
max_field_size=8190,
lingering_time=30,
lingering_timeout=5,
lingering_time=30.0,
lingering_timeout=5.0,
**kwargs):

# process deprecated params
Expand Down Expand Up @@ -220,6 +220,7 @@ def start(self):
or response handling. Connection is being closed always unless
keep_alive(True) specified.
"""
loop = self._loop
reader = self.reader
self.writer.set_tcp_nodelay(True)

Expand All @@ -234,7 +235,7 @@ def start(self):

# slow request timer
with Timeout(max(self._slow_request_timeout,
self._keepalive_timeout), loop=self._loop):
self._keepalive_timeout), loop=loop):
# read request headers
httpstream = reader.set_parser(self._request_parser)
message = yield from httpstream.read()
Expand All @@ -252,7 +253,7 @@ def start(self):
'chunked' in message.headers.get(
hdrs.TRANSFER_ENCODING, '')):
payload = streams.FlowControlStreamReader(
reader, loop=self._loop)
reader, loop=loop)
reader.set_parser(
aiohttp.HttpPayloadParser(message), payload)
else:
Expand All @@ -270,15 +271,19 @@ def start(self):
'Start lingering close timer for %s sec.',
self._lingering_time)

end_time = self._loop.time() + self._lingering_time
now = loop.time()
end_time = now + self._lingering_time

with suppress(asyncio.TimeoutError,
errors.ClientDisconnectedError):
while self._loop.time() < end_time:
with Timeout(self._lingering_timeout,
loop=self._loop):
while not payload.is_eof() and now < end_time:
timeout = min(
end_time - now, self._lingering_timeout)
with Timeout(timeout, loop=loop):
# read and ignore
yield from payload.readany()

now = loop.time()
else:
reader.unset_parser()
if not self._keepalive or not self._keepalive_timeout:
Expand Down
8 changes: 4 additions & 4 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,12 @@ def test_lingering(srv, loop):
srv.reader.feed_data(
b'GET / HTTP/1.0\r\n'
b'Host: example.com\r\n'
b'Content-Length: 0\r\n\r\n')

srv.reader.feed_data(b'123')
b'Content-Length: 3\r\n\r\n')

yield from asyncio.sleep(0, loop=loop)
yield from asyncio.sleep(0.1, loop=loop)
assert not transport.close.called

srv.reader.feed_data(b'123')
srv.reader.feed_eof()

yield from asyncio.sleep(0, loop=loop)
Expand Down

0 comments on commit 4a59c4f

Please sign in to comment.