@@ -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
0 commit comments