Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
def reinit(hub=None):
    """
    reinit() -> None

    Prepare the gevent hub to run in a new (forked) process.

    This should be called *immediately* after :func:`os.fork` in the
    child process. This is done automatically by
    :func:`gevent.os.fork` or if the :mod:`os` module has been
    monkey-patched. If this function is not called in a forked
    process, symptoms may include hanging of functions like
    :func:`socket.getaddrinfo`, and the hub's threadpool is unlikely
    to work.

    .. note:: Registered fork watchers may or may not run before
       this function (and thus ``gevent.os.fork``) return. If they have
       not run, they will run "soon", after an iteration of the event loop.
       You can force this by inserting a few small (but non-zero) calls to :func:`sleep`
       after fork returns. (As of gevent 1.1 and before, fork watchers will
       not have run, but this may change in the future.)

    .. note:: This function may be removed in a future major release
       if the fork process can be more smoothly managed.

    .. warning:: See remarks in :func:`gevent.os.fork` about greenlets
       and event loop watchers in the child process.
    """
    # Note the signature line in the docstring: hub is not a public param.

    # The loop reinit function in turn calls libev's ev_loop_fork
    # function.
    hub = _get_hub() if hub is None else hub
    if hub is None:
        return

    # Note that we reinit the existing loop, not destroy it.
    # See https://github.com/gevent/gevent/issues/200.
    hub.loop.reinit()
    # libev's fork watchers are slow to fire because the only fire
    # at the beginning of a loop; due to our use of callbacks that
    # run at the end of the loop, that may be too late. The
    # threadpool and resolvers depend on the fork handlers being
    # run (specifically, the threadpool will fail in the forked
    # child if there were any threads in it, which there will be
    # if the resolver_thread was in use (the default) before the
    # fork.)
    #
    # If the forked process wants to use the threadpool or
    # resolver immediately (in a queued callback), it would hang.
    #
    # The below is a workaround. Fortunately, all of these
    # methods are idempotent and can be called multiple times
    # following a fork if the suddenly started working, or were
    # already working on some platforms. Other threadpools and fork handlers
    # will be called at an arbitrary time later ('soon')
    for obj in (hub._threadpool, hub._resolver,
                hub.periodic_monitoring_thread):
        getattr(obj, '_on_fork', lambda: None)()
Beispiel #5
0
def reinit(hub=None):
    """
    reinit() -> None

    Prepare the gevent hub to run in a new (forked) process.

    This should be called *immediately* after :func:`os.fork` in the
    child process. This is done automatically by
    :func:`gevent.os.fork` or if the :mod:`os` module has been
    monkey-patched. If this function is not called in a forked
    process, symptoms may include hanging of functions like
    :func:`socket.getaddrinfo`, and the hub's threadpool is unlikely
    to work.

    .. note:: Registered fork watchers may or may not run before
       this function (and thus ``gevent.os.fork``) return. If they have
       not run, they will run "soon", after an iteration of the event loop.
       You can force this by inserting a few small (but non-zero) calls to :func:`sleep`
       after fork returns. (As of gevent 1.1 and before, fork watchers will
       not have run, but this may change in the future.)

    .. note:: This function may be removed in a future major release
       if the fork process can be more smoothly managed.

    .. warning:: See remarks in :func:`gevent.os.fork` about greenlets
       and event loop watchers in the child process.
    """
    # Note the signature line in the docstring: hub is not a public param.

    # The loop reinit function in turn calls libev's ev_loop_fork
    # function.
    hub = _get_hub() if hub is None else hub
    if hub is None:
        return

    # Note that we reinit the existing loop, not destroy it.
    # See https://github.com/gevent/gevent/issues/200.
    hub.loop.reinit()
    # libev's fork watchers are slow to fire because the only fire
    # at the beginning of a loop; due to our use of callbacks that
    # run at the end of the loop, that may be too late. The
    # threadpool and resolvers depend on the fork handlers being
    # run (specifically, the threadpool will fail in the forked
    # child if there were any threads in it, which there will be
    # if the resolver_thread was in use (the default) before the
    # fork.)
    #
    # If the forked process wants to use the threadpool or
    # resolver immediately (in a queued callback), it would hang.
    #
    # The below is a workaround. Fortunately, all of these
    # methods are idempotent and can be called multiple times
    # following a fork if the suddenly started working, or were
    # already working on some platforms. Other threadpools and fork handlers
    # will be called at an arbitrary time later ('soon')
    for obj in (hub._threadpool, hub._resolver, hub.periodic_monitoring_thread):
        getattr(obj, '_on_fork', lambda: None)()
Beispiel #6
0
    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)
Beispiel #7
0
    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)