Commit dfeb0d02 authored by Jason Madden's avatar Jason Madden

Document that kill() is not always safe for greenlets that aren't generally...

Document that kill() is not always safe for greenlets that aren't generally exception safe. Link to article about same. Ref #846.
parent c2671f9f
...@@ -311,6 +311,24 @@ killing will remain blocked forever). ...@@ -311,6 +311,24 @@ killing will remain blocked forever).
<gevent.Greenlet.kill>` is not defined. See that function's <gevent.Greenlet.kill>` is not defined. See that function's
documentation for more details. documentation for more details.
.. caution:: Use care when killing greenlets, especially arbitrary
greenlets spawned by a library or otherwise executing
code you are not familiar with. If the code being
executed is not prepared to deal with exceptions, object
state may be corrupted. For example, if it has acquired a
``Lock`` but *does not* use a ``finally`` block to
release it, killing the greenlet at the wrong time could
result in the lock being permanently locked::
def func():
# DON'T DO THIS
lock.acquire()
socket.sendall(data) # This could raise many exceptions, including GreenletExit
lock.release()
`This document
<http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html>`_
describes a similar situation for threads.
Timeouts Timeouts
======== ========
......
...@@ -413,6 +413,12 @@ class Greenlet(greenlet): ...@@ -413,6 +413,12 @@ class Greenlet(greenlet):
immediately is if this greenlet had called immediately is if this greenlet had called
:func:`sleep(0.1) <gevent.sleep>`. :func:`sleep(0.1) <gevent.sleep>`.
.. caution::
Use care when killing greenlets. If the code executing is not
exception safe (e.g., makes proper use of ``finally``) then an
unexpected exception could result in corrupted state.
See also :func:`gevent.kill`. See also :func:`gevent.kill`.
:keyword type exception: The type of exception to raise in the greenlet. The default :keyword type exception: The type of exception to raise in the greenlet. The default
...@@ -673,6 +679,9 @@ def killall(greenlets, exception=GreenletExit, block=True, timeout=None): ...@@ -673,6 +679,9 @@ def killall(greenlets, exception=GreenletExit, block=True, timeout=None):
""" """
Forceably terminate all the ``greenlets`` by causing them to raise ``exception``. Forceably terminate all the ``greenlets`` by causing them to raise ``exception``.
.. caution:: Use care when killing greenlets. If they are not prepared for exceptions,
this could result in corrupted state.
:param greenlets: A **bounded** iterable of the non-None greenlets to terminate. :param greenlets: A **bounded** iterable of the non-None greenlets to terminate.
*All* the items in this iterable must be greenlets that belong to the same thread. *All* the items in this iterable must be greenlets that belong to the same thread.
:keyword exception: The exception to raise in the greenlets. By default this is :keyword exception: The exception to raise in the greenlets. By default this is
......
...@@ -199,6 +199,9 @@ def kill(greenlet, exception=GreenletExit): ...@@ -199,6 +199,9 @@ def kill(greenlet, exception=GreenletExit):
``kill()`` method, and neither do any created with :func:`spawn_raw`, ``kill()`` method, and neither do any created with :func:`spawn_raw`,
so you have to use this function. so you have to use this function.
.. caution:: Use care when killing greenlets. If they are not prepared for
exceptions, this could result in corrupted state.
.. versionchanged:: 1.1a2 .. versionchanged:: 1.1a2
If the ``greenlet`` has a :meth:`kill <Greenlet.kill>` method, calls it. This prevents a If the ``greenlet`` has a :meth:`kill <Greenlet.kill>` method, calls it. This prevents a
greenlet from being switched to for the first time after it's been greenlet from being switched to for the first time after it's been
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment