Skip to content

Commit

Permalink
fixed resolve_host race conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
ojii committed Aug 29, 2019
1 parent b35c9e3 commit 93dd365
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
11 changes: 6 additions & 5 deletions aiohttp/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,24 +778,25 @@ async def _resolve_host(self,

if (key in self._cached_hosts) and \
(not self._cached_hosts.expired(key)):
result = self._cached_hosts.next_addrs(key)

if traces:
for trace in traces:
await trace.send_dns_cache_hit(host)

return self._cached_hosts.next_addrs(key)
return result

if key in self._throttle_dns_events:
event = self._throttle_dns_events[key]
if traces:
for trace in traces:
await trace.send_dns_cache_hit(host)
await self._throttle_dns_events[key].wait()
await event.wait()
else:
self._throttle_dns_events[key] = \
EventResultOrError(self._loop)
if traces:
for trace in traces:
await trace.send_dns_cache_miss(host)
self._throttle_dns_events[key] = \
EventResultOrError(self._loop)
try:

if traces:
Expand Down
32 changes: 31 additions & 1 deletion tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from aiohttp import client, web
from aiohttp.client import ClientRequest, ClientTimeout
from aiohttp.client_reqrep import ConnectionKey
from aiohttp.connector import Connection, _DNSCacheTable
from aiohttp.connector import Connection, _DNSCacheTable, TCPConnector
from aiohttp.helpers import PY_37
from aiohttp.locks import EventResultOrError
from aiohttp.test_utils import make_mocked_coro, unused_port
from aiohttp.tracing import Trace
from conftest import needs_unix
Expand Down Expand Up @@ -2257,3 +2258,32 @@ def test_next_addrs_single(self, dns_cache_table) -> None:

addrs = dns_cache_table.next_addrs('foo')
assert addrs == ['127.0.0.1']


async def test_connector_cache_trace_race():
class DummyTracer:
async def send_dns_cache_hit(self, *args, **kwargs):
connector._cached_hosts.remove(("", 0))

token = object()
connector = TCPConnector()
connector._cached_hosts.add(("", 0), [token])

traces = [DummyTracer()]
assert await connector._resolve_host("", 0, traces) == [token]


async def test_connector_throttle_trace_race(loop):
key = ("", 0)
token = object()

class DummyTracer:
async def send_dns_cache_hit(self, *args, **kwargs):
event = connector._throttle_dns_events.pop(key)
event.set()
connector._cached_hosts.add(key, [token])

connector = TCPConnector()
connector._throttle_dns_events[key] = EventResultOrError(loop)
traces = [DummyTracer()]
assert await connector._resolve_host("", 0, traces) == [token]

0 comments on commit 93dd365

Please sign in to comment.