diff --git a/py/c-extension/greenlet/greenlet.c b/py/c-extension/greenlet/greenlet.c index e98ba7344..dc926915c 100644 --- a/py/c-extension/greenlet/greenlet.c +++ b/py/c-extension/greenlet/greenlet.c @@ -394,7 +394,8 @@ static void g_initialstub(void* mark) /* in the new greenlet */ PyObject* args; PyObject* result; - ts_current->stack_start = (char*) 1; /* running */ + PyGreenlet* ts_self = ts_current; + ts_self->stack_start = (char*) 1; /* running */ args = ts_passaround; if (args == NULL) /* pending exception */ @@ -407,8 +408,8 @@ static void g_initialstub(void* mark) Py_DECREF(run); result = g_handle_exit(result); /* jump back to parent */ - ts_current->stack_start = NULL; /* dead */ - g_switch(ts_current->parent, result); + ts_self->stack_start = NULL; /* dead */ + g_switch(ts_self->parent, result); /* must not return from here! */ Py_FatalError("XXX memory exhausted at a very bad moment"); } @@ -463,6 +464,8 @@ static int kill_greenlet(PyGreenlet* self) because the 'parent' field chain would hold a reference */ PyObject* result; + if (!STATE_OK) + return -1; Py_INCREF(ts_current); self->parent = ts_current; /* Send the greenlet a GreenletExit exception. */ diff --git a/py/c-extension/greenlet/test_greenlet.py b/py/c-extension/greenlet/test_greenlet.py index 4bc484634..4b7d99d46 100644 --- a/py/c-extension/greenlet/test_greenlet.py +++ b/py/c-extension/greenlet/test_greenlet.py @@ -142,3 +142,17 @@ def test_frame(): assert not g assert next == "meaning of life" assert g.gr_frame is None + +def test_thread_bug(): + if not thread: + py.test.skip("this is a test about thread") + import time + def runner(x): + g = greenlet(lambda: time.sleep(x)) + g.switch() + t1 = threading.Thread(target=runner, args=(0.2,)) + t2 = threading.Thread(target=runner, args=(0.3,)) + t1.start() + t2.start() + t1.join() + t2.join()