summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2015-04-09 12:47:36 +0200
committerSergey Shepelev <temotor@gmail.com>2015-04-09 15:26:19 +0300
commit94069846055e397d031e0513e14d58064c3f444e (patch)
treec8b4f14749290b0fb0ac155eeafa9ce94540392d
parent268fd83d3a4e3cce7219c2ae5452f1f2f12d7107 (diff)
downloadeventlet-threading_join.tar.gz
Issue #223: Fix threading monkey-patching on py3.4threading_join
Fix the monkey-patching of the threading module on Python 3.4. Instead of removing the thread state lock, patch the _bootstrap_inner() method to release it.
-rw-r--r--eventlet/green/thread.py16
-rw-r--r--tests/isolated/patched_threading_join.py23
-rw-r--r--tests/patcher_test.py4
3 files changed, 40 insertions, 3 deletions
diff --git a/eventlet/green/thread.py b/eventlet/green/thread.py
index 7bd24d4..5c7446f 100644
--- a/eventlet/green/thread.py
+++ b/eventlet/green/thread.py
@@ -52,10 +52,20 @@ def start_new_thread(function, args=(), kwargs=None):
# With monkey patching, eventlet uses green threads without python
# thread state, so the lock is not automatically released.
#
- # Disable the thread state lock to avoid dead locks.
+ # Wrap _bootstrap_inner() to release explicitly the thread state lock
+ # when the thread completes.
thread = function.__self__
- thread._set_tstate_lock = lambda: None
- thread._wait_for_tstate_lock = lambda *args, **kw: None
+ 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)
diff --git a/tests/isolated/patched_threading_join.py b/tests/isolated/patched_threading_join.py
new file mode 100644
index 0000000..4361f52
--- /dev/null
+++ b/tests/isolated/patched_threading_join.py
@@ -0,0 +1,23 @@
+# Issue #223: test threading.Thread.join with monkey-patching
+import eventlet
+
+# no standard tests in this file, ignore
+__test__ = False
+
+
+if __name__ == '__main__':
+ eventlet.monkey_patch()
+
+ import threading
+ import time
+
+ sleeper = threading.Thread(target=time.sleep, args=(1,))
+ start = time.time()
+ sleeper.start()
+ sleeper.join()
+ dt = time.time() - start
+
+ if dt < 1.0:
+ raise Exception("test failed: dt=%s" % dt)
+
+ print('pass')
diff --git a/tests/patcher_test.py b/tests/patcher_test.py
index 2a42e3c..b20ae70 100644
--- a/tests/patcher_test.py
+++ b/tests/patcher_test.py
@@ -502,3 +502,7 @@ def test_importlib_lock():
def test_threading_condition():
tests.run_isolated('patcher_threading_condition.py')
+
+
+def test_threading_join():
+ tests.run_isolated('patched_threading_join.py')