| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 523aefb commit 7816278
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,7 +34,7 @@ | |||
| 34 | 34 | import time | |
| 35 | 35 | import warnings | |
| 36 | 36 | from collections import OrderedDict | |
| 37 | - from typing import Dict, Iterable, List, Optional, Sequence, Union, cast | ||
| 37 | + from typing import Dict, Iterable, List, Optional, Union, cast | ||
| 38 | 38 | from typing import Any, Callable, Set, Tuple # noqa # used in type hints | |
| 39 | 39 | ||
| 40 | 40 | import ifaddr | |
@@ -1337,39 +1337,51 @@ def __init__(self, zc: 'Zeroconf') -> None: | |||
| 1337 | 1337 | self.zc = zc | |
| 1338 | 1338 | self.readers = {} # type: Dict[socket.socket, Listener] | |
| 1339 | 1339 | self.timeout = 5 | |
| 1340 | + self.cache_cleanup_interval_ms = 10000.0 | ||
| 1340 | 1341 | self.condition = threading.Condition() | |
| 1341 | 1342 | self.socketpair = socket.socketpair() | |
| 1343 | + self._last_cache_cleanup = 0.0 | ||
| 1342 | 1344 | self.start() | |
| 1343 | 1345 | self.name = "zeroconf-Engine-%s" % (getattr(self, 'native_id', self.ident),) | |
| 1344 | 1346 | ||
| 1345 | 1347 | def run(self) -> None: | |
| 1346 | 1348 | while not self.zc.done: | |
| 1347 | - with self.condition: | ||
| 1348 | - rs = list(self.readers.keys()) | ||
| 1349 | - if len(rs) == 0: | ||
| 1350 | - # No sockets to manage, but we wait for the timeout | ||
| 1351 | - # or addition of a socket | ||
| 1349 | + rs = list(self.readers.keys()) | ||
| 1350 | + if not rs: | ||
| 1351 | + # No sockets to manage, but we wait for the timeout | ||
| 1352 | + # or addition of a socket | ||
| 1353 | + with self.condition: | ||
| 1352 | 1354 | self.condition.wait(self.timeout) | |
| 1355 | + continue | ||
| 1356 | + | ||
| 1357 | + try: | ||
| 1358 | + rs.append(self.socketpair[0]) | ||
| 1359 | + rr, wr, er = select.select(rs, [], [], self.timeout) | ||
| 1360 | + | ||
| 1361 | + if self.zc.done: | ||
| 1362 | + return | ||
| 1363 | + | ||
| 1364 | + for socket_ in rr: | ||
| 1365 | + reader = self.readers.get(socket_) | ||
| 1366 | + if reader: | ||
| 1367 | + reader.handle_read(socket_) | ||
| 1368 | + | ||
| 1369 | + if self.socketpair[0] in rr: | ||
| 1370 | + # Clear the socket's buffer | ||
| 1371 | + self.socketpair[0].recv(128) | ||
| 1372 | + | ||
| 1373 | + except (select.error, socket.error) as e: | ||
| 1374 | + # If the socket was closed by another thread, during | ||
| 1375 | + # shutdown, ignore it and exit | ||
| 1376 | + if e.args[0] not in (errno.EBADF, errno.ENOTCONN) or not self.zc.done: | ||
| 1377 | + raise | ||
| 1378 | + | ||
| 1379 | + now = current_time_millis() | ||
| 1380 | + if now - self._last_cache_cleanup >= self.cache_cleanup_interval_ms: | ||
| 1381 | + self._last_cache_cleanup = now | ||
| 1382 | + for record in self.zc.cache.expire(now): | ||
| 1383 | + self.zc.update_record(now, record) | ||
| 1353 | 1384 | ||
| 1354 | - if len(rs) != 0: | ||
| 1355 | - try: | ||
| 1356 | - rs = rs + [self.socketpair[0]] | ||
| 1357 | - rr, wr, er = select.select(cast(Sequence[Any], rs), [], [], self.timeout) | ||
| 1358 | - if not self.zc.done: | ||
| 1359 | - for socket_ in rr: | ||
| 1360 | - reader = self.readers.get(socket_) | ||
| 1361 | - if reader: | ||
| 1362 | - reader.handle_read(socket_) | ||
| 1363 | - | ||
| 1364 | - if self.socketpair[0] in rr: | ||
| 1365 | - # Clear the socket's buffer | ||
| 1366 | - self.socketpair[0].recv(128) | ||
| 1367 | - | ||
| 1368 | - except (select.error, socket.error) as e: | ||
| 1369 | - # If the socket was closed by another thread, during | ||
| 1370 | - # shutdown, ignore it and exit | ||
| 1371 | - if e.args[0] not in (errno.EBADF, errno.ENOTCONN) or not self.zc.done: | ||
| 1372 | - raise | ||
| 1373 | 1385 | self.socketpair[0].close() | |
| 1374 | 1386 | self.socketpair[1].close() | |
| 1375 | 1387 | ||
@@ -1464,32 +1476,6 @@ def handle_read(self, socket_: socket.socket) -> None: | |||
| 1464 | 1476 | self.zc.handle_response(msg) | |
| 1465 | 1477 | ||
| 1466 | 1478 | ||
| 1467 | - class Reaper(threading.Thread): | ||
| 1468 | - | ||
| 1469 | - """A Reaper is used by this module to remove cache entries that | ||
| 1470 | - have expired.""" | ||
| 1471 | - | ||
| 1472 | - def __init__(self, zc: 'Zeroconf') -> None: | ||
| 1473 | - threading.Thread.__init__(self) | ||
| 1474 | - self.daemon = True | ||
| 1475 | - self.zc = zc | ||
| 1476 | - self.start() | ||
| 1477 | - self.name = "zeroconf-Reaper_%s" % (getattr(self, 'native_id', self.ident),) | ||
| 1478 | - | ||
| 1479 | - def run(self) -> None: | ||
| 1480 | - """Perodic removal of expired entries from the cache.""" | ||
| 1481 | - while True: | ||
| 1482 | - with self.zc.reaper_condition: | ||
| 1483 | - self.zc.reaper_condition.wait(10) | ||
| 1484 | - | ||
| 1485 | - if self.zc.done: | ||
| 1486 | - return | ||
| 1487 | - | ||
| 1488 | - now = current_time_millis() | ||
| 1489 | - for record in self.zc.cache.expire(now): | ||
| 1490 | - self.zc.update_record(now, record) | ||
| 1491 | - | ||
| 1492 | - | ||
| 1493 | 1479 | class Signal: | |
| 1494 | 1480 | def __init__(self) -> None: | |
| 1495 | 1481 | self._handlers = [] # type: List[Callable[..., None]] | |
@@ -2505,7 +2491,6 @@ def __init__( | |||
| 2505 | 2491 | self.cache = DNSCache() | |
| 2506 | 2492 | ||
| 2507 | 2493 | self.condition = threading.Condition() | |
| 2508 | - self.reaper_condition = threading.Condition() | ||
| 2509 | 2494 | ||
| 2510 | 2495 | # Ensure we create the lock before | |
| 2511 | 2496 | # we add the listener as we could get | |
@@ -2519,7 +2504,6 @@ def __init__( | |||
| 2519 | 2504 | if self.multi_socket: | |
| 2520 | 2505 | for s in self._respond_sockets: | |
| 2521 | 2506 | self.engine.add_reader(self.listener, s) | |
| 2522 | - self.reaper = Reaper(self) | ||
| 2523 | 2507 | ||
| 2524 | 2508 | self.debug = None # type: Optional[DNSOutgoing] | |
| 2525 | 2509 | ||
@@ -2538,11 +2522,6 @@ def notify_all(self) -> None: | |||
| 2538 | 2522 | with self.condition: | |
| 2539 | 2523 | self.condition.notify_all() | |
| 2540 | 2524 | ||
| 2541 | - def notify_reaper(self) -> None: | ||
| 2542 | - """Notifies reaper""" | ||
| 2543 | - with self.reaper_condition: | ||
| 2544 | - self.reaper_condition.notify_all() | ||
| 2545 | - | ||
| 2546 | 2525 | def get_service_info(self, type_: str, name: str, timeout: int = 3000) -> Optional[ServiceInfo]: | |
| 2547 | 2526 | """Returns network's service information for a particular | |
| 2548 | 2527 | name and type, or None if no service matches by the timeout, | |
@@ -2987,7 +2966,5 @@ def close(self) -> None: | |||
| 2987 | 2966 | ||
| 2988 | 2967 | # shutdown the rest | |
| 2989 | 2968 | self.notify_all() | |
| 2990 | - self.notify_reaper() | ||
| 2991 | - self.reaper.join() | ||
| 2992 | 2969 | for s in self._respond_sockets: | |
| 2993 | 2970 | s.close() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -529,6 +529,17 @@ def test_launch_and_close(self): | |||
| 529 | 529 | rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default) | |
| 530 | 530 | rv.close() | |
| 531 | 531 | ||
| 532 | + def test_launch_and_close_unicast(self): | ||
| 533 | + rv = r.Zeroconf(interfaces=r.InterfaceChoice.All, unicast=True) | ||
| 534 | + rv.close() | ||
| 535 | + rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default, unicast=True) | ||
| 536 | + rv.close() | ||
| 537 | + | ||
| 538 | + def test_close_multiple_times(self): | ||
| 539 | + rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default) | ||
| 540 | + rv.close() | ||
| 541 | + rv.close() | ||
| 542 | + | ||
| 532 | 543 | @unittest.skipIf(not socket.has_ipv6, 'Requires IPv6') | |
| 533 | 544 | @unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled') | |
| 534 | 545 | def test_launch_and_close_v4_v6(self): | |
@@ -966,9 +977,11 @@ def test_reaper(self): | |||
| 966 | 977 | zeroconf.cache.add(record_with_10s_ttl) | |
| 967 | 978 | zeroconf.cache.add(record_with_1s_ttl) | |
| 968 | 979 | entries_with_cache = list(itertools.chain(*[cache.entries_with_name(name) for name in cache.names()])) | |
| 969 | - time.sleep(1.05) | ||
| 970 | - zeroconf.notify_reaper() | ||
| 971 | - time.sleep(0.05) | ||
| 980 | + zeroconf.engine.cache_cleanup_interval_ms = 10 | ||
| 981 | + time.sleep(1) | ||
| 982 | + with zeroconf.engine.condition: | ||
| 983 | + zeroconf.engine._notify() | ||
| 984 | + time.sleep(0.1) | ||
| 972 | 985 | entries = list(itertools.chain(*[cache.entries_with_name(name) for name in cache.names()])) | |
| 973 | 986 | zeroconf.close() | |
| 974 | 987 | assert entries != original_entries | |
| Back | FazBrowse Home | New Git URL |
0 commit comments