Add python-eventlet package to MOS 8.0 repository
[packages/trusty/python-eventlet.git] / python-eventlet / eventlet / green / thread.py
similarity index 68%
rename from eventlet/eventlet/green/thread.py
rename to python-eventlet/eventlet/green/thread.py
index 236031089521045f7c298c2b79ecba115f4639a7..5c7446fa2ba91926d5d07bb150a5bb59a1c34099 100644 (file)
@@ -3,6 +3,7 @@ from eventlet.support.six.moves import _thread as __thread
 from eventlet.support import greenlets as greenlet, six
 from eventlet import greenthread
 from eventlet.semaphore import Semaphore as LockType
+import sys
 
 
 __patched__ = ['get_ident', 'start_new_thread', 'start_new', 'allocate_lock',
@@ -43,6 +44,29 @@ def __thread_body(func, args, kwargs):
 
 
 def start_new_thread(function, args=(), kwargs=None):
+    if (sys.version_info >= (3, 4)
+            and getattr(function, '__module__', '') == 'threading'
+            and hasattr(function, '__self__')):
+        # Since Python 3.4, threading.Thread uses an internal lock
+        # automatically released when the python thread state is deleted.
+        # With monkey patching, eventlet uses green threads without python
+        # thread state, so the lock is not automatically released.
+        #
+        # Wrap _bootstrap_inner() to release explicitly the thread state lock
+        # when the thread completes.
+        thread = function.__self__
+        bootstrap_inner = thread._bootstrap_inner
+
+        def wrap_bootstrap_inner():
+            try:
+                bootstrap_inner()
+            finally:
+                # The lock can be cleared (ex: by a fork())
+                if thread._tstate_lock is not None:
+                    thread._tstate_lock.release()
+
+        thread._bootstrap_inner = wrap_bootstrap_inner
+
     kwargs = kwargs or {}
     g = greenthread.spawn_n(__thread_body, function, args, kwargs)
     return get_ident(g)