Commit 4bbef52f authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1304 from gevent/issue1302

Find greenlets in Cython code, keeping the GIL.
parents 03e2e391 3c9f6057
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
implementations. Place the required package or module on `sys.path` implementations. Place the required package or module on `sys.path`
first. first.
- Reduce the chances that using the blocking monitor functionality
could result in apparently random ``SystemError:
Objects/tupleobject.c: bad argument to internal function``. Reported
in :issue:`1302` by Ulrich Petri.
1.3.7 (2018-10-12) 1.3.7 (2018-10-12)
================== ==================
......
cimport cython cimport cython
# This file must not cimport anything from gevent. # This file must not cimport anything from gevent.
cdef get_objects
cdef wref cdef wref
cdef BlockingSwitchOutError cdef BlockingSwitchOutError
...@@ -42,3 +42,6 @@ cdef class SwitchOutGreenletWithLoop(TrackedRawGreenlet): ...@@ -42,3 +42,6 @@ cdef class SwitchOutGreenletWithLoop(TrackedRawGreenlet):
cpdef switch(self) cpdef switch(self)
cpdef switch_out(self) cpdef switch_out(self)
cpdef list get_reachable_greenlets()
...@@ -11,6 +11,7 @@ from __future__ import division ...@@ -11,6 +11,7 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
from weakref import ref as wref from weakref import ref as wref
from gc import get_objects
from greenlet import greenlet from greenlet import greenlet
...@@ -65,6 +66,21 @@ class SwitchOutGreenletWithLoop(TrackedRawGreenlet): ...@@ -65,6 +66,21 @@ class SwitchOutGreenletWithLoop(TrackedRawGreenlet):
def switch_out(self): def switch_out(self):
raise BlockingSwitchOutError('Impossible to call blocking function in the event loop callback') raise BlockingSwitchOutError('Impossible to call blocking function in the event loop callback')
def get_reachable_greenlets():
# We compile this loop with Cython so that it's faster, and so that
# the GIL isn't dropped at unpredictable times during the loop.
# Dropping the GIL could lead to accessing partly constructed objects
# in undefined states (particularly, tuples). This helps close a hole
# where a `SystemError: Objects/tupleobject.c bad argument to internal function`
# could get raised. (Note that this probably doesn't completely close the hole,
# if other threads have dropped the GIL, but hopefully the speed makes that
# more rare.) See https://github.com/gevent/gevent/issues/1302
return [
x for x in get_objects()
if isinstance(x, greenlet) and not getattr(x, 'greenlet_tree_is_ignored', False)
]
def _init(): def _init():
greenlet_init() # pylint:disable=undefined-variable greenlet_init() # pylint:disable=undefined-variable
......
...@@ -6,13 +6,11 @@ Low-level utilities. ...@@ -6,13 +6,11 @@ Low-level utilities.
from __future__ import absolute_import, print_function, division from __future__ import absolute_import, print_function, division
import functools import functools
import gc
import pprint import pprint
import sys import sys
import traceback import traceback
from greenlet import getcurrent from greenlet import getcurrent
from greenlet import greenlet as RawGreenlet
from gevent._compat import PYPY from gevent._compat import PYPY
from gevent._compat import thread_mod_name from gevent._compat import thread_mod_name
...@@ -454,20 +452,16 @@ class GreenletTree(object): ...@@ -454,20 +452,16 @@ class GreenletTree(object):
@classmethod @classmethod
def _forest(cls): def _forest(cls):
from gevent._greenlet_primitives import get_reachable_greenlets
main_greenlet = cls._root_greenlet(getcurrent()) main_greenlet = cls._root_greenlet(getcurrent())
trees = {} trees = {}
roots = {} roots = {}
current_tree = roots[main_greenlet] = trees[main_greenlet] = cls(main_greenlet) current_tree = roots[main_greenlet] = trees[main_greenlet] = cls(main_greenlet)
glets = get_reachable_greenlets()
for ob in glets:
for ob in gc.get_objects():
if not isinstance(ob, RawGreenlet):
continue
if getattr(ob, 'greenlet_tree_is_ignored', False):
continue
spawn_parent = cls.__spawning_parent(ob) spawn_parent = cls.__spawning_parent(ob)
if spawn_parent is None: if spawn_parent is None:
......
...@@ -189,6 +189,10 @@ disabled_tests = [ ...@@ -189,6 +189,10 @@ disabled_tests = [
# The host this wants to use, sha256.tbs-internet.com, is not resolvable # The host this wants to use, sha256.tbs-internet.com, is not resolvable
# right now (2015-10-10), and we need to get Windows wheels # right now (2015-10-10), and we need to get Windows wheels
# This started timing out randomly on Travis in oct/nov 2018. It appears
# to be something with random number generation taking too long.
'test_ssl.BasicSocketTests.test_random_fork',
# Relies on the repr of objects (Py3) # Relies on the repr of objects (Py3)
'test_ssl.BasicSocketTests.test_dealloc_warn', 'test_ssl.BasicSocketTests.test_dealloc_warn',
......
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