From e71f41e389071f339a52ab13f7f1be656ebb4306 Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Aug 03 2012 00:12:52 +0000 Subject: Merge branch 'master' into el6 Conflicts: python-eventlet.spec --- diff --git a/.gitignore b/.gitignore index 4ec653c..5e00d63 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ eventlet-0.9.7.tar.gz eventlet-0.9.9.tar.gz /eventlet-0.9.12.tar.gz /eventlet-0.9.16.tar.gz +/eventlet-0.9.17.tar.gz diff --git a/dummythread_leak.patch b/dummythread_leak.patch deleted file mode 100644 index 85d2355..0000000 --- a/dummythread_leak.patch +++ /dev/null @@ -1,359 +0,0 @@ -diff -Naur eventlet-0.9.16.orig/eventlet/green/threading.py eventlet-0.9.16/eventlet/green/threading.py ---- eventlet-0.9.16.orig/eventlet/green/threading.py 2012-03-27 11:39:17.557782270 +0000 -+++ eventlet-0.9.16/eventlet/green/threading.py 2012-03-27 11:39:42.604113535 +0000 -@@ -1,9 +1,16 @@ -+"""Implements the standard threading module, using greenthreads.""" - from eventlet import patcher - from eventlet.green import thread - from eventlet.green import time -+from eventlet.support import greenlets as greenlet - - __patched__ = ['_start_new_thread', '_allocate_lock', '_get_ident', '_sleep', -- 'local', 'stack_size', 'Lock'] -+ 'local', 'stack_size', 'Lock', 'currentThread', -+ 'current_thread', '_after_fork', '_shutdown'] -+ -+__orig_threading = patcher.original('threading') -+__threadlocal = __orig_threading.local() -+ - - patcher.inject('threading', - globals(), -@@ -11,3 +18,103 @@ - ('time', time)) - - del patcher -+ -+ -+_count = 1 -+class _GreenThread(object): -+ """Wrapper for GreenThread objects to provide Thread-like attributes -+ and methods""" -+ def __init__(self, g): -+ global _count -+ self._g = g -+ self._name = 'GreenThread-%d' % _count -+ _count += 1 -+ -+ def __repr__(self): -+ return '<_GreenThread(%s, %r)>' % (self._name, self._g) -+ -+ def join(self, timeout=None): -+ return self._g.wait() -+ -+ @property -+ def name(self): -+ return self._name -+ -+ @name.setter -+ def name(self, name): -+ self._name = str(name) -+ -+ def getName(self): -+ return self.name -+ get_name = getName -+ -+ def setName(self, name): -+ self.name = name -+ set_name = setName -+ -+ @property -+ def ident(self): -+ return id(self._g) -+ -+ def isAlive(self): -+ return True -+ is_alive = isAlive -+ -+ @property -+ def daemon(self): -+ return True -+ -+ def isDaemon(self): -+ return self.daemon -+ is_daemon = isDaemon -+ -+ -+__threading = None -+ -+def _fixup_thread(t): -+ # Some third-party packages (lockfile) will try to patch the -+ # threading.Thread class with a get_name attribute if it doesn't -+ # exist. Since we might return Thread objects from the original -+ # threading package that won't get patched, let's make sure each -+ # individual object gets patched too our patched threading.Thread -+ # class has been patched. This is why monkey patching can be bad... -+ global __threading -+ if not __threading: -+ __threading = __import__('threading') -+ -+ if (hasattr(__threading.Thread, 'get_name') and -+ not hasattr(t, 'get_name')): -+ t.get_name = t.getName -+ return t -+ -+ -+def current_thread(): -+ g = greenlet.getcurrent() -+ if not g: -+ # Not currently in a greenthread, fall back to standard function -+ return _fixup_thread(__orig_threading.current_thread()) -+ -+ try: -+ active = __threadlocal.active -+ except AttributeError: -+ active = __threadlocal.active = {} -+ -+ 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.current_thread()) -+ else: -+ t = active[id(g)] = _GreenThread(g) -+ -+ return t -+ -+currentThread = current_thread -diff -Naur eventlet-0.9.16.orig/eventlet/patcher.py eventlet-0.9.16/eventlet/patcher.py ---- eventlet-0.9.16.orig/eventlet/patcher.py 2012-03-27 11:39:17.558782283 +0000 -+++ eventlet-0.9.16/eventlet/patcher.py 2012-03-27 11:39:35.148014914 +0000 -@@ -223,7 +223,6 @@ - on.setdefault(modname, default_on) - - modules_to_patch = [] -- patched_thread = False - if on['os'] and not already_patched.get('os'): - modules_to_patch += _green_os_modules() - already_patched['os'] = True -@@ -234,7 +233,6 @@ - modules_to_patch += _green_socket_modules() - already_patched['socket'] = True - if on['thread'] and not already_patched.get('thread'): -- patched_thread = True - modules_to_patch += _green_thread_modules() - already_patched['thread'] = True - if on['time'] and not already_patched.get('time'): -@@ -266,27 +264,9 @@ - patched_attr = getattr(mod, attr_name, None) - if patched_attr is not None: - setattr(orig_mod, attr_name, patched_attr) -- -- # hacks ahead; this is necessary to prevent a KeyError on program exit -- if patched_thread: -- _patch_main_thread(sys.modules['threading']) - finally: - imp.release_lock() - --def _patch_main_thread(mod): -- """This is some gnarly patching specific to the threading module; -- threading will always be initialized prior to monkeypatching, and -- its _active dict will have the wrong key (it uses the real thread -- id but once it's patched it will use the greenlet ids); so what we -- do is rekey the _active dict so that the main thread's entry uses -- the greenthread key. Other threads' keys are ignored.""" -- thread = original('thread') -- curthread = mod._active.pop(thread.get_ident(), None) -- if curthread: -- import eventlet.green.thread -- mod._active[eventlet.green.thread.get_ident()] = curthread -- -- - def is_monkey_patched(module): - """Returns True if the given module is monkeypatched currently, False if - not. *module* can be either the module itself or its name. -diff -Naur eventlet-0.9.16.orig/tests/patcher_test.py eventlet-0.9.16/tests/patcher_test.py ---- eventlet-0.9.16.orig/tests/patcher_test.py 2012-03-27 11:39:17.560782309 +0000 -+++ eventlet-0.9.16/tests/patcher_test.py 2012-03-27 11:39:42.604113535 +0000 -@@ -293,5 +293,183 @@ - self.assertEqual(output, "done\n", output) - - -+class Threading(ProcessBase): -+ def test_orig_thread(self): -+ new_mod = """import eventlet -+eventlet.monkey_patch() -+from eventlet import patcher -+import threading -+_threading = patcher.original('threading') -+def test(): -+ print repr(threading.current_thread()) -+t = _threading.Thread(target=test) -+t.start() -+t.join() -+print len(threading._active) -+print len(_threading._active) -+""" -+ self.write_to_tempfile("newmod", new_mod) -+ output, lines = self.launch_subprocess('newmod') -+ self.assertEqual(len(lines), 4, "\n".join(lines)) -+ self.assert_(lines[0].startswith('= 6.1 where python 2.6 has the backported timeout support Patch1: subprocess_timeout.patch -# From https://bitbucket.org/which_linden/eventlet/changeset/2a02c700f51a/raw/ -# https://bitbucket.org/which_linden/eventlet/changeset/55b6de9bd947/raw/ -# https://bitbucket.org/which_linden/eventlet/changeset/6603e234fc56/raw/ -# https://bitbucket.org/which_linden/eventlet/changeset/f3fd4562f347/raw/ -# To plug _DummyThread leak described at https://bugs.launchpad.net/nova/+bug/903199 -Patch2: dummythread_leak.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildArch: noarch @@ -50,7 +44,6 @@ find -name '.*' -type f -exec rm {} \; sed -i -e 's/ //g' tests/mock.py sed -i -e '1d' eventlet/support/greendns.py %patch1 -p1 -b .subprocess_timeout -%patch2 -p1 -b .dummythread_leak %build %{__python} setup.py build @@ -64,7 +57,7 @@ chmod a-x tests/mock.py %install rm -rf %{buildroot} %{__python} setup.py install -O1 --skip-build --root %{buildroot} - + %clean rm -rf %{buildroot} @@ -80,6 +73,9 @@ rm -rf %{buildroot} %doc doc/_build/html examples tests %changelog +* Fri Aug 03 2012 Pádraig Brady