Commit 1cc22839 authored by Jason Madden's avatar Jason Madden

Note dependency on Cython 0.23.4 or above, and revert semaphore workaround for older versions.

parent 201781bb
...@@ -41,8 +41,9 @@ Development ...@@ -41,8 +41,9 @@ Development
To install the latest development version:: To install the latest development version::
pip install cython git+git://github.com/gevent/gevent.git#egg=gevent pip install 'cython>=0.23.4' git+git://github.com/gevent/gevent.git#egg=gevent
.. note:: You must have Cython installed to build a checkout.
Running Tests Running Tests
------------- -------------
...@@ -50,6 +51,7 @@ Running Tests ...@@ -50,6 +51,7 @@ Running Tests
There are a few different ways to run the tests. To simply run the There are a few different ways to run the tests. To simply run the
tests on one version of Python during development, try this:: tests on one version of Python during development, try this::
pip install cython>=0.23.4
python setup.py build python setup.py build
cd greentest cd greentest
PYTHONPATH=.. python testrunner.py --config ../known_failures.py PYTHONPATH=.. python testrunner.py --config ../known_failures.py
......
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
``gevent.lock.Semaphore`` subclasses. If monkey-patched, this could ``gevent.lock.Semaphore`` subclasses. If monkey-patched, this could
also apply to ``threading.Semaphore`` objects. Reported in also apply to ``threading.Semaphore`` objects. Reported in
:issue:`660` by Jay Oster. :issue:`660` by Jay Oster.
- PyPy: Work around the worst case of a bug in Cython 0.23.3 that - PyPy: Cython version 0.23.4 or later must be used to avoid a memory
caused tuples to leak when releasing ``gevent.lock.Semaphore`` leak (`details`_). Thanks to Jay Oster.
objects that were linked to (e.g., when a StreamServer had a spawn
limit). .. _details: https://mail.python.org/pipermail/cython-devel/2015-October/004571.html
1.1b5 (Sep 18, 2015) 1.1b5 (Sep 18, 2015)
==================== ====================
......
...@@ -9,7 +9,7 @@ cdef class Semaphore: ...@@ -9,7 +9,7 @@ cdef class Semaphore:
cpdef rawlink(self, object callback) cpdef rawlink(self, object callback)
cpdef unlink(self, object callback) cpdef unlink(self, object callback)
cpdef _start_notify(self) cpdef _start_notify(self)
cdef _notify_links(self) cpdef _notify_links(self)
cdef _do_wait(self, object timeout) cdef _do_wait(self, object timeout)
cpdef int wait(self, object timeout=*) except -1000 cpdef int wait(self, object timeout=*) except -1000
cpdef bint acquire(self, int blocking=*, object timeout=*) except -1000 cpdef bint acquire(self, int blocking=*, object timeout=*) except -1000
......
...@@ -63,15 +63,10 @@ class Semaphore(object): ...@@ -63,15 +63,10 @@ class Semaphore(object):
# if needed. (it has a __bool__ method that tells whether it has # if needed. (it has a __bool__ method that tells whether it has
# been run; once it's run once---at the end of the loop---it becomes # been run; once it's run once---at the end of the loop---it becomes
# false.) # false.)
# Note that we pass Semaphore.__notify_links and not self._notify_links. # NOTE: Passing the bound method will cause a memory leak on PyPy
# This avoids having Cython create a bound method, which on PyPy 2.6.1, # with Cython <= 0.23.3. You must use >= 0.23.4.
# shows up as a leak, at least in the short term (possibly due to the cycles?) # See https://bitbucket.org/pypy/pypy/issues/2149/memory-leak-for-python-subclass-of-cpyext#comment-22371546
# Simply passing it to Python, where Python doesn't keep a reference to it, self._notifier = get_hub().loop.run_callback(self._notify_links)
# shows as a leak. (It's probably this is the same leak as the CallOneArg leak documented in _notify_links.)
# Note2: The method and tuple objects still show as a leak until the event
# loop is allowed to run, e.g., with gevent.sleep(). Manually running the callbacks
# isn't enough.
self._notifier = get_hub().loop.run_callback(Semaphore._notify_links, self)
def _notify_links(self): def _notify_links(self):
# Subclasses CANNOT override. This is a cdef method. # Subclasses CANNOT override. This is a cdef method.
...@@ -83,11 +78,6 @@ class Semaphore(object): ...@@ -83,11 +78,6 @@ class Semaphore(object):
# no need to keep it around until that point (making it potentially climb # no need to keep it around until that point (making it potentially climb
# into older GC generations, notably on PyPy) # into older GC generations, notably on PyPy)
notifier = self._notifier notifier = self._notifier
# XXX Cython 0.23.3 and before, at least, have a bug calling arguments of one method on PyPy,
# such that a tuple leaks every time.
# See https://bitbucket.org/pypy/pypy/issues/2149/memory-leak-for-python-subclass-of-cpyext#comment-22371546
# So we do a workaround and force tuple packing/unpacking
args = (self,)
try: try:
while True: while True:
self._dirty = False self._dirty = False
...@@ -99,7 +89,7 @@ class Semaphore(object): ...@@ -99,7 +89,7 @@ class Semaphore(object):
if self.counter <= 0: if self.counter <= 0:
return return
try: try:
link(*args) link(self) # Must use Cython >= 0.23.4 on PyPy else this leaks memory
except: except:
getcurrent().handle_error((link, self), *sys.exc_info()) getcurrent().handle_error((link, self), *sys.exc_info())
if self._dirty: if self._dirty:
...@@ -128,7 +118,7 @@ class Semaphore(object): ...@@ -128,7 +118,7 @@ class Semaphore(object):
if self._links is None: if self._links is None:
self._links = [callback] self._links = [callback]
else: else:
self._links.append(callback) # XXX might leak a tuple on PyPy. See _notify_links self._links.append(callback)
self._dirty = True self._dirty = True
def unlink(self, callback): def unlink(self, callback):
...@@ -138,7 +128,7 @@ class Semaphore(object): ...@@ -138,7 +128,7 @@ class Semaphore(object):
Remove the callback set by :meth:`rawlink` Remove the callback set by :meth:`rawlink`
""" """
try: try:
self._links.remove(callback) # XXX might leak a tuple on PyPy. See _notify_links self._links.remove(callback)
self._dirty = True self._dirty = True
except (ValueError, AttributeError): except (ValueError, AttributeError):
pass pass
...@@ -157,7 +147,6 @@ class Semaphore(object): ...@@ -157,7 +147,6 @@ class Semaphore(object):
try: try:
# As a tiny efficiency optimization, avoid allocating a timer # As a tiny efficiency optimization, avoid allocating a timer
# if not needed. # if not needed.
# XXX might leak a tuple on PyPy. See _notify_links
timer = Timeout.start_new(timeout) if timeout is not None else None timer = Timeout.start_new(timeout) if timeout is not None else None
try: try:
try: try:
......
...@@ -345,6 +345,8 @@ elif PYPY: ...@@ -345,6 +345,8 @@ elif PYPY:
# cost of some speed (one trivial semaphore micro-benchmark put the pure-python version # cost of some speed (one trivial semaphore micro-benchmark put the pure-python version
# at around 1s and the compiled version at around 4s). Some clever subclassing # at around 1s and the compiled version at around 4s). Some clever subclassing
# and having only the bare minimum be in cython might help reduce that penalty. # and having only the bare minimum be in cython might help reduce that penalty.
# NOTE: You must use version 0.23.4 or later to avoid a memory leak.
# https://mail.python.org/pipermail/cython-devel/2015-October/004571.html
Extension(name="gevent._semaphore", Extension(name="gevent._semaphore",
sources=["gevent/gevent._semaphore.c"])] sources=["gevent/gevent._semaphore.c"])]
include_package_data = True include_package_data = True
...@@ -360,7 +362,10 @@ else: ...@@ -360,7 +362,10 @@ else:
run_make = True run_make = True
if run_make and os.path.exists("Makefile"): if run_make and os.path.exists("Makefile"):
setup_requires = ['cython'] # This is effectively pointless and serves only for
# documentation/metadata, because we run 'make' *before* we run
# setup(), so installing cython happens too late.
setup_requires = ['cython >= 0.23.4']
else: else:
setup_requires = [] setup_requires = []
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment