Hello community, here is the log from the commit of package python-eventlet for openSUSE:Factory checked in at 2013-02-08 14:44:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-eventlet (Old) and /work/SRC/openSUSE:Factory/.python-eventlet.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-eventlet", Maintainer is "[email protected]" Changes: -------- --- /work/SRC/openSUSE:Factory/python-eventlet/python-eventlet.changes 2013-01-20 08:16:20.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-eventlet.new/python-eventlet.changes 2013-02-08 23:24:46.000000000 +0100 @@ -1,0 +2,11 @@ +Fri Feb 8 11:19:25 UTC 2013 - [email protected] + +- Update to version 0.12.1: + * zmq: Fix 100% busy CPU in idle after .bind(PUB) + * greenio: Fix socket.settimeout() did not switch back to blocking mode + * greenio: socket.dup() made excess fcntl syscalls + * setup: Remove legacy --without-greenlet option and unused httplib2 dependency + * wsgi: environ[REMOTE_PORT], also available in log_format, log accept event + * tests: Support libzmq 3.0 SNDHWM option + +------------------------------------------------------------------- Old: ---- eventlet-0.11.0.tar.gz New: ---- eventlet-0.12.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-eventlet.spec ++++++ --- /var/tmp/diff_new_pack.970e0Y/_old 2013-02-08 23:24:51.000000000 +0100 +++ /var/tmp/diff_new_pack.970e0Y/_new 2013-02-08 23:24:51.000000000 +0100 @@ -17,7 +17,7 @@ Name: python-eventlet -Version: 0.11.0 +Version: 0.12.1 Release: 0 Url: http://eventlet.net Summary: Highly concurrent networking library ++++++ eventlet-0.11.0.tar.gz -> eventlet-0.12.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/AUTHORS new/eventlet-0.12.1/AUTHORS --- old/eventlet-0.11.0/AUTHORS 2013-01-14 00:46:06.000000000 +0100 +++ new/eventlet-0.12.1/AUTHORS 2013-01-24 11:18:17.000000000 +0100 @@ -30,6 +30,7 @@ * Nick V * Daniele Varrazzo * Ryan Williams +* Geoff Salmon Linden Lab Contributors ----------------------- @@ -78,3 +79,5 @@ * Eric Windisch, zmq getsockopt(EVENTS) wake correct threads (pull request 22) * Raymond Lu, fixing busy-wait in eventlet.green.ssl.socket.sendall() * Thomas Grainger, webcrawler example small fix, "requests" library import bug report +* Peter Portante, save syscalls in socket.dup(), environ[REMOTE_PORT] in wsgi +* Peter Skirko, fixing socket.settimeout(0) bug diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/NEWS new/eventlet-0.12.1/NEWS --- old/eventlet-0.11.0/NEWS 2013-01-13 23:43:27.000000000 +0100 +++ new/eventlet-0.12.1/NEWS 2013-01-24 11:18:17.000000000 +0100 @@ -1,3 +1,12 @@ +0.12 +==== +* zmq: Fix 100% busy CPU in idle after .bind(PUB) (thanks to Geoff Salmon) +* greenio: Fix socket.settimeout() did not switch back to blocking mode (thanks to Peter Skirko) +* greenio: socket.dup() made excess fcntl syscalls (thanks to Peter Portante) +* setup: Remove legacy --without-greenlet option and unused httplib2 dependency (thanks to Thomas Grainger) +* wsgi: environ[REMOTE_PORT], also available in log_format, log accept event (thanks to Peter Portante) +* tests: Support libzmq 3.0 SNDHWM option (thanks to Geoff Salmon) + 0.11 ==== * ssl: Fix 100% busy CPU in socket.sendall() (thanks to Raymon Lu) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/PKG-INFO new/eventlet-0.12.1/PKG-INFO --- old/eventlet-0.11.0/PKG-INFO 2013-01-14 01:13:35.000000000 +0100 +++ new/eventlet-0.12.1/PKG-INFO 2013-01-26 02:04:37.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: eventlet -Version: 0.11.0 +Version: 0.12.1 Summary: Highly concurrent networking library Home-page: http://eventlet.net Author: Linden Lab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/eventlet/__init__.py new/eventlet-0.12.1/eventlet/__init__.py --- old/eventlet-0.11.0/eventlet/__init__.py 2013-01-13 23:16:35.000000000 +0100 +++ new/eventlet-0.12.1/eventlet/__init__.py 2013-01-26 02:00:16.000000000 +0100 @@ -1,4 +1,4 @@ -version_info = (0, 11, 0) +version_info = (0, 12, 1) __version__ = ".".join(map(str, version_info)) try: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/eventlet/green/zmq.py new/eventlet-0.12.1/eventlet/green/zmq.py --- old/eventlet-0.11.0/eventlet/green/zmq.py 2013-01-13 22:41:38.000000000 +0100 +++ new/eventlet-0.12.1/eventlet/green/zmq.py 2013-01-23 10:34:03.000000000 +0100 @@ -205,8 +205,13 @@ # Some events arrived at the zmq socket. This may mean # there's a message that can be read or there's space for # a message to be written. - self._eventlet_send_event.wake() - self._eventlet_recv_event.wake() + send_wake = self._eventlet_send_event.wake() + recv_wake = self._eventlet_recv_event.wake() + if not send_wake and not recv_wake: + # if no waiting send or recv thread was woken up, then + # force the zmq socket's events to be processed to + # avoid repeated wakeups + _Socket_getsockopt(self, EVENTS) hub = hubs.get_hub() self._eventlet_listener = hub.add(hub.READ, self.getsockopt(FD), event) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/eventlet/greenio.py new/eventlet-0.12.1/eventlet/greenio.py --- old/eventlet-0.11.0/eventlet/greenio.py 2013-01-12 01:52:22.000000000 +0100 +++ new/eventlet-0.12.1/eventlet/greenio.py 2013-01-24 11:18:17.000000000 +0100 @@ -97,8 +97,10 @@ "(Windows pipes don't support non-blocking I/O)") # We managed to import fcntl. fileno = fd.fileno() - flags = fcntl.fcntl(fileno, fcntl.F_GETFL) - fcntl.fcntl(fileno, fcntl.F_SETFL, flags | os.O_NONBLOCK) + orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL) + new_flags = orig_flags | os.O_NONBLOCK + if new_flags != orig_flags: + fcntl.fcntl(fileno, fcntl.F_SETFL, new_flags) else: # socket supports setblocking() setblocking(0) @@ -114,8 +116,13 @@ """ Green version of socket.socket class, that is intended to be 100% API-compatible. + + It also recognizes the keyword parameter, 'set_nonblocking=True'. + Pass False to indicate that socket is already in non-blocking mode + to save syscalls. """ def __init__(self, family_or_realsock=socket.AF_INET, *args, **kwargs): + should_set_nonblocking = kwargs.pop('set_nonblocking', True) if isinstance(family_or_realsock, (int, long)): fd = _original_socket(family_or_realsock, *args, **kwargs) else: @@ -129,7 +136,8 @@ except AttributeError: self._timeout = socket.getdefaulttimeout() - set_nonblocking(fd) + if should_set_nonblocking: + set_nonblocking(fd) self.fd = fd # when client calls setblocking(0) or settimeout(0) the socket must # act non-blocking @@ -209,8 +217,7 @@ def dup(self, *args, **kw): sock = self.fd.dup(*args, **kw) - set_nonblocking(sock) - newsock = type(self)(sock) + newsock = type(self)(sock, set_nonblocking=False) newsock.settimeout(self.gettimeout()) return newsock @@ -313,8 +320,10 @@ if howlong < 0.0: raise ValueError('Timeout value out of range') if howlong == 0.0: - self.setblocking(howlong) + self.act_non_blocking = True + self._timeout = 0.0 else: + self.act_non_blocking = False self._timeout = howlong def gettimeout(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/eventlet/wsgi.py new/eventlet-0.12.1/eventlet/wsgi.py --- old/eventlet-0.11.0/eventlet/wsgi.py 2013-01-12 01:52:22.000000000 +0100 +++ new/eventlet-0.12.1/eventlet/wsgi.py 2013-01-24 11:18:17.000000000 +0100 @@ -18,6 +18,7 @@ MAX_HEADER_LINE = 8192 MAX_TOTAL_HEADER_SIZE = 65536 MINIMUM_CHUNK_SIZE = 4096 +# %(client_port)s is also available DEFAULT_LOG_FORMAT= ('%(client_ip)s - - [%(date_time)s] "%(request_line)s"' ' %(status_code)s %(body_length)s %(wall_seconds).6f') @@ -429,16 +430,17 @@ for hook, args, kwargs in self.environ['eventlet.posthooks']: hook(self.environ, *args, **kwargs) - + if self.server.log_output: - - self.server.log_message(self.server.log_format % dict( - client_ip=self.get_client_ip(), - date_time=self.log_date_time_string(), - request_line=self.requestline, - status_code=status_code[0], - body_length=length[0], - wall_seconds=finish - start)) + self.server.log_message(self.server.log_format % { + 'client_ip': self.get_client_ip(), + 'client_port': self.client_address[1], + 'date_time': self.log_date_time_string(), + 'request_line': self.requestline, + 'status_code': status_code[0], + 'body_length': length[0], + 'wall_seconds': finish - start, + }) def get_client_ip(self): client_ip = self.client_address[0] @@ -473,6 +475,7 @@ env['SERVER_NAME'] = host env['SERVER_PORT'] = str(port) env['REMOTE_ADDR'] = self.client_address[0] + env['REMOTE_PORT'] = str(self.client_address[1]) env['GATEWAY_INTERFACE'] = 'CGI/1.1' for h in self.headers.headers: @@ -594,8 +597,8 @@ minimum_chunk_size=None, log_x_forwarded_for=True, custom_pool=None, - keepalive=True, - log_output=True, + keepalive=True, + log_output=True, log_format=DEFAULT_LOG_FORMAT, url_length_limit=MAX_REQUEST_LINE, debug=True): @@ -654,10 +657,13 @@ port = '' serv.log.write("(%s) wsgi starting up on %s://%s%s/\n" % ( - os.getpid(), scheme, host, port)) + serv.pid, scheme, host, port)) while True: try: client_socket = sock.accept() + if debug: + serv.log.write("(%s) accepted %r\n" % ( + serv.pid, client_socket[1])) try: pool.spawn_n(serv.process_request, client_socket) except AttributeError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/eventlet.egg-info/PKG-INFO new/eventlet-0.12.1/eventlet.egg-info/PKG-INFO --- old/eventlet-0.11.0/eventlet.egg-info/PKG-INFO 2013-01-14 01:13:35.000000000 +0100 +++ new/eventlet-0.12.1/eventlet.egg-info/PKG-INFO 2013-01-26 02:04:33.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: eventlet -Version: 0.11.0 +Version: 0.12.1 Summary: Highly concurrent networking library Home-page: http://eventlet.net Author: Linden Lab diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/setup.py new/eventlet-0.12.1/setup.py --- old/eventlet-0.11.0/setup.py 2013-01-12 01:52:22.000000000 +0100 +++ new/eventlet-0.12.1/setup.py 2013-01-24 11:18:17.000000000 +0100 @@ -1,17 +1,8 @@ #!/usr/bin/env python - - from setuptools import find_packages, setup from eventlet import __version__ from os import path -import sys -requirements = [] -for flag, req in [('--without-greenlet','greenlet >= 0.3')]: - if flag in sys.argv: - sys.argv.remove(flag) - else: - requirements.append(req) setup( name='eventlet', @@ -21,7 +12,9 @@ author_email='[email protected]', url='http://eventlet.net', packages=find_packages(exclude=['tests', 'benchmarks']), - install_requires=requirements, + install_requires=( + 'greenlet >= 0.3', + ), zip_safe=False, long_description=open( path.join( @@ -29,21 +22,20 @@ 'README' ) ).read(), - test_suite = 'nose.collector', - tests_require = 'httplib2', + test_suite='nose.collector', classifiers=[ - "License :: OSI Approved :: MIT License", - "Programming Language :: Python", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python :: 2.4", - "Programming Language :: Python :: 2.5", - "Programming Language :: Python :: 2.6", - "Programming Language :: Python :: 2.7", - "Topic :: Internet", - "Topic :: Software Development :: Libraries :: Python Modules", - "Intended Audience :: Developers", - "Development Status :: 4 - Beta"] - ) - + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python :: 2.4", + "Programming Language :: Python :: 2.5", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Topic :: Internet", + "Topic :: Software Development :: Libraries :: Python Modules", + "Intended Audience :: Developers", + "Development Status :: 4 - Beta", + ] +) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/tests/greenio_test.py new/eventlet-0.12.1/tests/greenio_test.py --- old/eventlet-0.11.0/tests/greenio_test.py 2013-01-12 03:10:06.000000000 +0100 +++ new/eventlet-0.12.1/tests/greenio_test.py 2013-01-24 11:18:17.000000000 +0100 @@ -4,12 +4,13 @@ from eventlet.hubs import get_hub from eventlet.green import socket, time from eventlet.support import get_errno -import errno +import array +import errno import eventlet +import fcntl import os import sys -import array import tempfile, shutil @@ -528,6 +529,58 @@ port = eventlet.listen(('127.0.0.1', 0)).getsockname()[1] self.assertRaises(socket.error, eventlet.connect, ('127.0.0.1', port)) + def test_zero_timeout_and_back(self): + listen = eventlet.listen(('', 0)) + # Keep reference to server side of socket + server = eventlet.spawn(listen.accept) + client = eventlet.connect(listen.getsockname()) + + client.settimeout(0.05) + # Now must raise socket.timeout + self.assertRaises(socket.timeout, client.recv, 1) + + client.settimeout(0) + # Now must raise socket.error with EAGAIN + try: + client.recv(1) + assert False + except socket.error, e: + assert get_errno(e) == errno.EAGAIN + + client.settimeout(0.05) + # Now socket.timeout again + self.assertRaises(socket.timeout, client.recv, 1) + server.wait() + + def test_default_nonblocking(self): + sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL) + assert flags & os.O_NONBLOCK + + sock2 = socket.socket(sock1.fd) + flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) + assert flags & os.O_NONBLOCK + + def test_dup_nonblocking(self): + sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + flags = fcntl.fcntl(sock1.fd.fileno(), fcntl.F_GETFL) + assert flags & os.O_NONBLOCK + + sock2 = sock1.dup() + flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) + assert flags & os.O_NONBLOCK + + def test_skip_nonblocking(self): + sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + fd = sock1.fd.fileno() + flags = fcntl.fcntl(fd, fcntl.F_GETFL) + flags = fcntl.fcntl(fd, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) + assert flags & os.O_NONBLOCK == 0 + + sock2 = socket.socket(sock1.fd, set_nonblocking=False) + flags = fcntl.fcntl(sock2.fd.fileno(), fcntl.F_GETFL) + assert flags & os.O_NONBLOCK == 0 + class TestGreenPipe(LimitedTestCase): @skip_on_windows @@ -798,5 +851,16 @@ assert maxstartdiff * 2 < runlengths[0], "Largest difference in starting times more than twice the shortest running time!" assert runlengths[0] * 2 > runlengths[-1], "Longest runtime more than twice as long as shortest!" + +def test_set_nonblocking(): + sock = _orig_sock.socket(socket.AF_INET, socket.SOCK_DGRAM) + fileno = sock.fileno() + orig_flags = fcntl.fcntl(fileno, fcntl.F_GETFL) + assert orig_flags & os.O_NONBLOCK == 0 + greenio.set_nonblocking(sock) + new_flags = fcntl.fcntl(fileno, fcntl.F_GETFL) + assert new_flags == (orig_flags | os.O_NONBLOCK) + + if __name__ == '__main__': main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/eventlet-0.11.0/tests/zmq_test.py new/eventlet-0.12.1/tests/zmq_test.py --- old/eventlet-0.11.0/tests/zmq_test.py 2013-01-13 22:59:04.000000000 +0100 +++ new/eventlet-0.12.1/tests/zmq_test.py 2013-01-23 10:34:03.000000000 +0100 @@ -3,7 +3,7 @@ from eventlet import event, spawn, sleep, patcher, semaphore from eventlet.hubs import get_hub, _threadlocal, use_hub from nose.tools import * -from tests import mock, LimitedTestCase, using_pyevent, skip_unless +from tests import check_idle_cpu_usage, mock, LimitedTestCase, using_pyevent, skip_unless from unittest import TestCase from threading import Thread @@ -348,7 +348,13 @@ num_recvs = 30 done = event.Event() - sender.setsockopt(zmq.HWM, 10) + try: + SNDHWM = zmq.SNDHWM + except AttributeError: + # ZeroMQ <3.0 + SNDHWM = zmq.HWM + + sender.setsockopt(SNDHWM, 10) sender.setsockopt(zmq.SNDBUF, 10) receiver.setsockopt(zmq.RCVBUF, 10) @@ -403,6 +409,44 @@ events = sock2.getsockopt(zmq.EVENTS) self.assertEqual(events & zmq.POLLIN, zmq.POLLIN) + @skip_unless(zmq_supported) + def test_cpu_usage_after_bind(self): + """zmq eats CPU after PUB socket .bind() + + https://bitbucket.org/which_linden/eventlet/issue/128 + + According to the ZeroMQ documentation, the socket file descriptor + can be readable without any pending messages. So we need to ensure + that Eventlet wraps around ZeroMQ sockets do not create busy loops. + + A naive way to test it is to measure resource usage. This will require + some tuning to set appropriate acceptable limits. + """ + sock = self.context.socket(zmq.PUB) + self.sockets.append(sock) + sock.bind_to_random_port("tcp://127.0.0.1") + sleep() + check_idle_cpu_usage(0.2, 0.1) + + @skip_unless(zmq_supported) + def test_cpu_usage_after_pub_send_or_dealer_recv(self): + """zmq eats CPU after PUB send or DEALER recv. + + Same https://bitbucket.org/which_linden/eventlet/issue/128 + """ + pub, sub, _port = self.create_bound_pair(zmq.PUB, zmq.SUB) + sub.setsockopt(zmq.SUBSCRIBE, "") + sleep() + pub.send('test_send') + check_idle_cpu_usage(0.2, 0.1) + + sender, receiver, _port = self.create_bound_pair(zmq.DEALER, zmq.DEALER) + sleep() + sender.send('test_recv') + msg = receiver.recv() + self.assertEqual(msg, 'test_recv') + check_idle_cpu_usage(0.2, 0.1) + class TestQueueLock(LimitedTestCase): @skip_unless(zmq_supported) -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
