Commit dbb55b10 authored by Jason Madden's avatar Jason Madden

Straighten out the test__threading_2 reference leak.

This should fix the refleaks in general (it was a frame object that was leaking).
Submitting to CI for broad test, and if it is good then we will try backing out the test__util changes too.

Also make it possible for gevent.config to show help.
parent 07569cc3
......@@ -234,7 +234,6 @@ def cythonize1(ext):
'.',
]
try:
print("XXX: Drop compile_time_env")
new_ext = cythonize(
[ext],
include_path=standard_include_paths,
......
......@@ -8,6 +8,11 @@
#include <Python.h>
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
#endif
#ifdef __cplusplus
extern "C" {
#endif
......@@ -31,7 +36,7 @@ extern "C" {
need to increment the refcount before returning, not just to match the
official functions, but to match what Cython expects an API like this to
return. Otherwise we get crashes. */
static void* PyFrame_GetBack(PyFrameObject* frame)
static PyObject* PyFrame_GetBack(PyFrameObject* frame)
{
PyObject* result = (PyObject*)((PyFrameObject*)frame)->f_back;
Py_XINCREF(result);
......@@ -41,13 +46,38 @@ static void* PyFrame_GetBack(PyFrameObject* frame)
static PyObject* PyFrame_GetCode(PyFrameObject* frame)
{
PyObject* result = (PyObject*)((PyFrameObject*)frame)->f_code;
Py_XINCREF(result);
/* There is always code! */
Py_INCREF(result);
return result;
}
#endif /* support 3.8 and below. */
#endif
/**
Unlike PyFrame_GetBack, which can return NULL,
this method is guaranteed to return a new reference to an object.
The object is either a frame object or None.
This is necessary to help Cython deal correctly with reference counting.
(There are other ways of dealing with this having to do with exactly how
variables/return types are declared IIRC, but this is the most
straightforward. Still, it is critical that the cython declaration of
this function use ``object`` as its return type.)
*/
static PyObject* Gevent_PyFrame_GetBack(PyFrameObject* frame)
{
PyObject* back = (PyObject*)PyFrame_GetBack(frame);
if (back) {
return back;
}
Py_RETURN_NONE;
}
#ifdef __cplusplus
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif
#endif /* _COMPAT_H */
......@@ -6,6 +6,11 @@ This should be used as ``from gevent import config``. That variable
is an object of :class:`Config`.
.. versionadded:: 1.3a2
.. versionchanged:: NEXT
Invoking this module like ``python -m gevent._config`` will
print a help message about available configuration properties.
This is handy to quickly look for environment variables.
"""
from __future__ import print_function, absolute_import, division
......@@ -206,6 +211,12 @@ class Config(object):
def __dir__(self):
return list(self.settings)
def print_help(self):
for k, v in self.settings.items():
print(k)
print(textwrap.indent(v.__doc__.lstrip(), ' ' * 4))
print()
class ImportableSetting(object):
......@@ -473,7 +484,9 @@ class TrackGreenletTree(BoolSettingMixin, Setting):
Setting this to a false value will make spawning `Greenlet`
objects and using `spawn_raw` faster, but the
``spawning_greenlet``, ``spawn_tree_locals`` and ``spawning_stack``
will not be captured.
will not be captured. Setting this to a false value can also
reduce memory usage because capturing the stack captures
some information about Python frames.
.. versionadded:: 1.3b1
"""
......@@ -717,3 +730,7 @@ try:
Loop().get()
except ImportError: # pragma: no cover
pass
if __name__ == '__main__':
config.print_help()
......@@ -57,19 +57,13 @@ ctypedef object CodeType
cdef extern from "_compat.h":
int PyFrame_GetLineNumber(FrameType frame)
CodeType PyFrame_GetCode(FrameType frame)
void* PyFrame_GetBack(FrameType frame)
object Gevent_PyFrame_GetBack(FrameType frame)
ctypedef class types.FrameType [object PyFrameObject]:
pass
@cython.nonecheck(False)
cdef inline FrameType get_f_back(FrameType frame):
# We cannot just call the original version, because it
# can return NULL even when there is no exception set. That confuses
# Cython and CPython. We need to manually check for NULL here.
f_back = PyFrame_GetBack(frame)
if f_back != NULL:
return <FrameType>f_back
cdef inline object get_f_back(FrameType frame):
return Gevent_PyFrame_GetBack(frame)
cdef void _init()
......
......@@ -413,7 +413,6 @@ class ThreadTests(unittest.TestCase):
if not hasattr(sys, 'pypy_version_info'):
def test_no_refcycle_through_target(self):
self.skipTest('WARNING: LEAKING.Debugging.')
class RunSelfFunction(object):
def __init__(self, should_raise):
# The links in this refcycle from Thread back to self
......
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