def __init__(self, loop=None, default=None): WaitOperationsGreenlet.__init__(self, None, None) self.thread_ident = get_thread_ident() if hasattr(loop, 'run'): if default is not None: raise TypeError("Unexpected argument: default") self.loop = loop elif get_loop() is not None: # Reuse a loop instance previously set by # destroying a hub without destroying the associated # loop. See #237 and #238. self.loop = get_loop() else: if default is None and self.thread_ident != MAIN_THREAD_IDENT: default = False if loop is None: loop = self.backend self.loop = self.loop_class(flags=loop, default=default) # pylint:disable=not-callable self._resolver = None self._threadpool = None self.format_context = GEVENT_CONFIG.format_context Hub._hub_counter += 1 self.minimal_ident = Hub._hub_counter
def destroy(self, destroy_loop=None): """ Destroy this hub and clean up its resources. If you manually create hubs, you *should* call this method before disposing of the hub object reference. """ if self.periodic_monitoring_thread is not None: self.periodic_monitoring_thread.kill() self.periodic_monitoring_thread = None if self._resolver is not None: self._resolver.close() del self._resolver if self._threadpool is not None: self._threadpool.kill() del self._threadpool if destroy_loop is None: destroy_loop = not self.loop.default if destroy_loop: if get_loop() is self.loop: # Don't let anyone try to reuse this set_loop(None) self.loop.destroy() else: # Store in case another hub is created for this # thread. set_loop(self.loop) self.loop = None if _get_hub() is self: set_hub(None)
def destroy(self, destroy_loop=None): if self.periodic_monitoring_thread is not None: self.periodic_monitoring_thread.kill() self.periodic_monitoring_thread = None if self._resolver is not None: self._resolver.close() del self._resolver if self._threadpool is not None: self._threadpool.kill() del self._threadpool if destroy_loop is None: destroy_loop = not self.loop.default if destroy_loop: if get_loop() is self.loop: # Don't let anyone try to reuse this set_loop(None) self.loop.destroy() else: # Store in case another hub is created for this # thread. set_loop(self.loop) self.loop = None if _get_hub() is self: set_hub(None)
def destroy(self, destroy_loop=None): """ Destroy this hub and clean up its resources. If you manually create hubs, or you use a hub or the gevent blocking API from multiple native threads, you *should* call this method before disposing of the hub object reference. Once this is done, it is impossible to continue running the hub. Attempts to use the blocking gevent API with pre-existing objects from this native thread and bound to this hub will fail. .. versionchanged:: 20.5.1 Ensure that Python stack frames and greenlets referenced by this hub are cleaned up. This guarantees that switching to the hub again is not safe after this. (It was never safe, but it's even less safe.) """ if self.periodic_monitoring_thread is not None: self.periodic_monitoring_thread.kill() self.periodic_monitoring_thread = None if self._resolver is not None: self._resolver.close() del self._resolver if self._threadpool is not None: self._threadpool.kill() del self._threadpool # Let the frame be cleaned up by causing the run() function to # exit. This is the only way to guarantee that the hub itself # and the main greenlet, if this was a secondary thread, get # cleaned up. Otherwise there are likely to be reference # cycles still around. We MUST do this before we destroy the # loop; if we destroy the loop and then switch into the hub, # things will go VERY, VERY wrong. try: self.throw(GreenletExit) except LoopExit: pass if destroy_loop is None: destroy_loop = not self.loop.default if destroy_loop: if get_loop() is self.loop: # Don't let anyone try to reuse this set_loop(None) self.loop.destroy() else: # Store in case another hub is created for this # thread. set_loop(self.loop) self.loop = None if _get_hub() is self: set_hub(None)
def destroy(self, destroy_loop=None): """ Destroy this hub and clean up its resources. If you manually create hubs, or you use a hub or the gevent blocking API from multiple native threads, you *should* call this method before disposing of the hub object reference. Ideally, this should be called from the same thread running the hub, but it can be called from other threads after that thread has exited. Once this is done, it is impossible to continue running the hub. Attempts to use the blocking gevent API with pre-existing objects from this native thread and bound to this hub will fail. .. versionchanged:: 20.5.1 Attempt to ensure that Python stack frames and greenlets referenced by this hub are cleaned up. This guarantees that switching to the hub again is not safe after this. (It was never safe, but it's even less safe.) Note that this only works if the hub is destroyed in the same thread it is running in. If the hub is destroyed by a different thread after a ``fork()``, for example, expect some garbage to leak. """ if destroy_loop is None: destroy_loop = not self.loop.default if self.periodic_monitoring_thread is not None: self.periodic_monitoring_thread.kill() self.periodic_monitoring_thread = None if self._resolver is not None: self._resolver.close() del self._resolver if self._threadpool is not None: self._threadpool.kill() del self._threadpool # Let the frame be cleaned up by causing the run() function to # exit. This is the only way to guarantee that the hub itself # and the main greenlet, if this was a secondary thread, get # cleaned up. Otherwise there are likely to be reference # cycles still around. We MUST do this before we destroy the # loop; if we destroy the loop and then switch into the hub, # things will go VERY, VERY wrong (because we will have destroyed # the C datastructures in the middle of the C function that's # using them; the best we can hope for is a segfault). try: self.throw(HubDestroyed(destroy_loop)) except LoopExit: # Expected. pass except GreenletError: # Must be coming from a different thread. # Note that python stack frames are likely to leak # in this case. pass if destroy_loop: if get_loop() is self.loop: # Don't let anyone try to reuse this set_loop(None) self.loop.destroy() else: # Store in case another hub is created for this # thread. set_loop(self.loop) self.loop = None if _get_hub() is self: set_hub(None)