Skip to content

Commit 7d8994b

Browse files
authored
Remove all calls to the executor in AsyncZeroconf (#653)
1 parent b940f87 commit 7d8994b

2 files changed

Lines changed: 40 additions & 13 deletions

File tree

zeroconf/_core.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ async def _async_cache_cleanup(self) -> None:
149149
async def _async_close(self) -> None:
150150
"""Cancel and wait for the cleanup task to finish."""
151151
self._async_shutdown()
152-
assert self._cache_cleanup_task is not None
153-
self._cache_cleanup_task.cancel()
154-
with contextlib.suppress(asyncio.CancelledError):
155-
await self._cache_cleanup_task
156-
self._cache_cleanup_task = None
152+
if self._cache_cleanup_task:
153+
self._cache_cleanup_task.cancel()
154+
with contextlib.suppress(asyncio.CancelledError):
155+
await self._cache_cleanup_task
156+
self._cache_cleanup_task = None
157157
await asyncio.sleep(0) # flush out any call soons
158158

159159
def _async_shutdown(self) -> None:
@@ -170,6 +170,8 @@ def close(self) -> None:
170170
if get_running_loop() == self.loop:
171171
self._async_shutdown()
172172
return
173+
if not self.loop.is_running():
174+
return
173175
asyncio.run_coroutine_threadsafe(self._async_close(), self.loop).result()
174176

175177

@@ -607,24 +609,48 @@ def async_send(self, out: DNSOutgoing, addr: Optional[str] = None, port: int = _
607609
# on send errors, log the exception and keep going
608610
self.log_exception_warning('Error sending through socket %d', s.fileno())
609611

610-
def close(self) -> None:
611-
"""Ends the background threads, and prevent this instance from
612-
servicing further queries."""
612+
def _close(self) -> None:
613+
"""Set global done and remove all service listeners."""
613614
if self._GLOBAL_DONE:
614615
return
615-
# remove service listeners
616-
self.unregister_all_services()
617616
self.remove_all_service_listeners()
618617
self._GLOBAL_DONE = True
619-
self.engine.close()
620-
# shutdown the rest
618+
619+
def _shutdown_threads(self) -> None:
620+
"""Shutdown any threads."""
621621
self.notify_all()
622622
if not self._loop_thread:
623623
return
624624
assert self.loop is not None
625625
self.loop.call_soon_threadsafe(self.loop.stop)
626626
self._loop_thread.join()
627627

628+
def close(self) -> None:
629+
"""Ends the background threads, and prevent this instance from
630+
servicing further queries.
631+
632+
This method is idempotent and irreversible.
633+
"""
634+
self.unregister_all_services()
635+
self._close()
636+
self.engine.close()
637+
self._shutdown_threads()
638+
639+
async def _async_close(self) -> None:
640+
"""Ends the background threads, and prevent this instance from
641+
servicing further queries.
642+
643+
This method is idempotent and irreversible.
644+
645+
This call only intended to be used by AsyncZeroconf
646+
647+
Callers are responsible for unregistering all services
648+
before calling this function
649+
"""
650+
self._close()
651+
await self.engine._async_close() # pylint: disable=protected-access
652+
self._shutdown_threads()
653+
628654
def __enter__(self) -> 'Zeroconf':
629655
return self
630656

zeroconf/aio.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,8 @@ async def async_close(self) -> None:
294294
await asyncio.wait_for(self.zeroconf.async_wait_for_start(), timeout=1)
295295
await self.async_remove_all_service_listeners()
296296
self.zeroconf.remove_notify_listener(self.async_notify)
297-
await self.loop.run_in_executor(None, self.zeroconf.close)
297+
await self.async_unregister_all_services()
298+
await self.zeroconf._async_close() # pylint: disable=protected-access
298299

299300
async def async_get_service_info(
300301
self, type_: str, name: str, timeout: int = 3000

0 commit comments

Comments
 (0)