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 @@
implementations. Place the required package or module on `sys.path`
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)
==================
......
cimport cython
# This file must not cimport anything from gevent.
cdef get_objects
cdef wref
cdef BlockingSwitchOutError
......@@ -42,3 +42,6 @@ cdef class SwitchOutGreenletWithLoop(TrackedRawGreenlet):
cpdef switch(self)
cpdef switch_out(self)
cpdef list get_reachable_greenlets()
......@@ -11,6 +11,7 @@ from __future__ import division
from __future__ import print_function
from weakref import ref as wref
from gc import get_objects
from greenlet import greenlet
......@@ -65,6 +66,21 @@ class SwitchOutGreenletWithLoop(TrackedRawGreenlet):
def switch_out(self):
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():
greenlet_init() # pylint:disable=undefined-variable
......
......@@ -6,13 +6,11 @@ Low-level utilities.
from __future__ import absolute_import, print_function, division
import functools
import gc
import pprint
import sys
import traceback
from greenlet import getcurrent
from greenlet import greenlet as RawGreenlet
from gevent._compat import PYPY
from gevent._compat import thread_mod_name
......@@ -454,20 +452,16 @@ class GreenletTree(object):
@classmethod
def _forest(cls):
from gevent._greenlet_primitives import get_reachable_greenlets
main_greenlet = cls._root_greenlet(getcurrent())
trees = {}
roots = {}
current_tree = roots[main_greenlet] = trees[main_greenlet] = cls(main_greenlet)
glets = get_reachable_greenlets()
for ob in gc.get_objects():
if not isinstance(ob, RawGreenlet):
continue
if getattr(ob, 'greenlet_tree_is_ignored', False):
continue
for ob in glets:
spawn_parent = cls.__spawning_parent(ob)
if spawn_parent is None:
......
......@@ -189,6 +189,10 @@ disabled_tests = [
# 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
# 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)
'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