diff options
author | Sergey Shepelev <temotor@gmail.com> | 2018-04-15 02:10:57 +0300 |
---|---|---|
committer | Sergey Shepelev <temotor@gmail.com> | 2018-04-15 03:16:28 +0300 |
commit | 1d6d8924a9da6a0cb839b81e785f99b6ac219a0e (patch) | |
tree | 601a925d2d1d5cd82413cfe0fb0f12fd9e14128f | |
parent | 69983c6d76e7c122d14a804b5932dfef00d8f7c8 (diff) | |
download | eventlet-147-jake.tar.gz |
green.threading: current_thread() did not see new monkey-patched threads; Thanks to Jake Tesler147-jake
https://github.com/eventlet/eventlet/issues/172
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | eventlet/green/threading.py | 51 | ||||
-rw-r--r-- | tests/isolated/patcher_threading_current.py | 25 | ||||
-rw-r--r-- | tests/patcher_test.py | 21 |
4 files changed, 62 insertions, 36 deletions
@@ -165,3 +165,4 @@ Thanks To * orishoshan * Matt Bennett * Ralf Haferkamp +* Jake Tesler diff --git a/eventlet/green/threading.py b/eventlet/green/threading.py index 3176261..a25a1f1 100644 --- a/eventlet/green/threading.py +++ b/eventlet/green/threading.py @@ -1,5 +1,5 @@ """Implements the standard threading module, using greenthreads.""" -from eventlet import patcher +import eventlet from eventlet.green import thread from eventlet.green import time from eventlet.support import greenlets as greenlet, six @@ -13,18 +13,17 @@ if six.PY2: else: __patched__ += ['get_ident', '_set_sentinel'] -__orig_threading = patcher.original('threading') +__orig_threading = eventlet.patcher.original('threading') __threadlocal = __orig_threading.local() +__patched_enumerate = None -patcher.inject( +eventlet.patcher.inject( 'threading', globals(), ('thread' if six.PY2 else '_thread', thread), ('time', time)) -del patcher - _count = 1 @@ -89,6 +88,7 @@ def _fixup_thread(t): def current_thread(): + global __patched_enumerate g = greenlet.getcurrent() if not g: # Not currently in a greenthread, fall back to standard function @@ -99,21 +99,34 @@ def current_thread(): except AttributeError: active = __threadlocal.active = {} + g_id = id(g) + t = active.get(g_id) + if t is not None: + return t + + # FIXME: move import from function body to top + # (jaketesler@github) Furthermore, I was unable to have the current_thread() return correct results from + # threading.enumerate() unless the enumerate() function was a) imported at runtime using the gross __import__() call + # and b) was hot-patched using patch_function(). + # https://github.com/eventlet/eventlet/issues/172#issuecomment-379421165 + if __patched_enumerate is None: + __patched_enumerate = eventlet.patcher.patch_function(__import__('threading').enumerate) + found = [th for th in __patched_enumerate() if th.ident == g_id] + if found: + return found[0] + + # Add green thread to active if we can clean it up on exit + def cleanup(g): + del active[g_id] try: - t = active[id(g)] - except KeyError: - # Add green thread to active if we can clean it up on exit - def cleanup(g): - del active[id(g)] - try: - g.link(cleanup) - except AttributeError: - # Not a GreenThread type, so there's no way to hook into - # the green thread exiting. Fall back to the standard - # function then. - t = _fixup_thread(__orig_threading.currentThread()) - else: - t = active[id(g)] = _GreenThread(g) + g.link(cleanup) + except AttributeError: + # Not a GreenThread type, so there's no way to hook into + # the green thread exiting. Fall back to the standard + # function then. + t = _fixup_thread(__orig_threading.current_thread()) + else: + t = active[g_id] = _GreenThread(g) return t diff --git a/tests/isolated/patcher_threading_current.py b/tests/isolated/patcher_threading_current.py new file mode 100644 index 0000000..2eb6676 --- /dev/null +++ b/tests/isolated/patcher_threading_current.py @@ -0,0 +1,25 @@ +# Threading.current_thread does not change when using greenthreads? +# https://github.com/eventlet/eventlet/issues/172 +__test__ = False + +if __name__ == '__main__': + import eventlet + eventlet.monkey_patch() + + import threading + + g = set() + + def fun(): + ct = threading.current_thread() + g.add(ct.name) + + ts = tuple(threading.Thread(target=fun, name='t{}'.format(i)) for i in range(3)) + for t in ts: + t.start() + for t in ts: + t.join() + + assert g == set(('t0', 't1', 't2')), repr(g) + + print('pass') diff --git a/tests/patcher_test.py b/tests/patcher_test.py index ff59400..00ee31f 100644 --- a/tests/patcher_test.py +++ b/tests/patcher_test.py @@ -312,23 +312,6 @@ print(len(_threading._active)) assert lines[1] == '1', lines assert lines[2] == '1', lines - def test_threading(self): - new_mod = """import eventlet -eventlet.monkey_patch() -import threading -def test(): - print(repr(threading.currentThread())) -t = threading.Thread(target=test) -t.start() -t.join() -print(len(threading._active)) -""" - self.write_to_tempfile("newmod", new_mod) - output, lines = self.launch_subprocess('newmod.py') - self.assertEqual(len(lines), 3, "\n".join(lines)) - assert lines[0].startswith('<_MainThread'), lines[0] - self.assertEqual(lines[1], "1", lines[1]) - def test_tpool(self): new_mod = """import eventlet eventlet.monkey_patch() @@ -520,3 +503,7 @@ def test_blocking_select_methods_are_deleted(): def test_regular_file_readall(): tests.run_isolated('regular_file_readall.py') + + +def test_threading_current(): + tests.run_isolated('patcher_threading_current.py') |