summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/tracer.c18
-rw-r--r--tests/test_concurrency.py18
2 files changed, 33 insertions, 3 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c
index 5a463fcb..79040d07 100644
--- a/coverage/tracer.c
+++ b/coverage/tracer.c
@@ -177,6 +177,8 @@ DataStack_grow(CTracer *self, DataStack *pdata_stack)
static int
CTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused)
{
+ PyObject * weakref = NULL;
+
#if COLLECT_STATS
self->stats.calls = 0;
self->stats.lines = 0;
@@ -203,7 +205,14 @@ CTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused)
if (DataStack_init(self, &self->data_stack)) {
return RET_ERROR;
}
- self->data_stack_index = PyDict_New();
+
+ weakref = PyImport_ImportModule("weakref");
+ if (weakref == NULL) {
+ return RET_ERROR;
+ }
+ self->data_stack_index = PyObject_CallMethod(weakref, "WeakKeyDictionary", NULL);
+ Py_XDECREF(weakref);
+
if (self->data_stack_index == NULL) {
STATS( self->stats.errors++; )
return RET_ERROR;
@@ -336,12 +345,15 @@ CTracer_set_pdata_stack(CTracer *self)
if (co_obj == NULL) {
return RET_ERROR;
}
- stack_index = PyDict_GetItem(self->data_stack_index, co_obj);
+ stack_index = PyObject_GetItem(self->data_stack_index, co_obj);
if (stack_index == NULL) {
+ /* PyObject_GetItem sets an exception if it didn't find the thing. */
+ PyErr_Clear();
+
/* A new concurrency object. Make a new data stack. */
the_index = self->data_stacks_used;
stack_index = MyInt_FromLong(the_index);
- if (PyDict_SetItem(self->data_stack_index, co_obj, stack_index) < 0) {
+ if (PyObject_SetItem(self->data_stack_index, co_obj, stack_index) < 0) {
STATS( self->stats.errors++; )
Py_XDECREF(co_obj);
Py_XDECREF(stack_index);
diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py
index 5ea756f6..6fbac4a6 100644
--- a/tests/test_concurrency.py
+++ b/tests/test_concurrency.py
@@ -201,6 +201,24 @@ class ConcurrencyTest(CoverageTest):
def test_greenlet_simple_code(self):
self.try_some_code(self.SIMPLE, "greenlet", greenlet)
+ def test_bug_330(self):
+ BUG_330 = """\
+ from weakref import WeakKeyDictionary
+ import eventlet
+
+ def do():
+ eventlet.sleep(.01)
+
+ gts = WeakKeyDictionary()
+ for _ in range(100):
+ gts[eventlet.spawn(do)] = True
+ eventlet.sleep(.005)
+
+ eventlet.sleep(.1)
+ print len(gts)
+ """
+ self.try_some_code(BUG_330, "eventlet", eventlet, "0\n")
+
def print_simple_annotation(code, linenos):
"""Print the lines in `code` with X for each line number in `linenos`."""