Skip to content

Commit 7e24943

Browse files
committed
g_switchstack was using a stack local variable, which it can't do.
Amusingly, this only caused issues on 64-bit Python 3.9 and 3.10 an Windows.
1 parent 1b7906c commit 7e24943

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ greenlet.egg-info/
1111
__pycache__/
1212
/.ropeproject/
1313
/MANIFEST
14+
benchmarks/*.json

src/greenlet/greenlet.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,15 +201,17 @@ class _GThreadState {
201201
switch_kwargs_w(0),
202202
origin_greenlet_s(0),
203203
switchstack_use_tracing(0)
204-
{};
204+
{
205+
fprintf(stderr, "Initialized thread state %p\n", this);
206+
};
205207

206208
// Only one of these, auto created per thread
207209
_GThreadState(const _GThreadState& other) = delete;
208210
_GThreadState& operator=(const _GThreadState& other) = delete;
209211

210212
~_GThreadState()
211213
{
212-
//fprintf(stderr, "Destructing thread %p\n", this);
214+
fprintf(stderr, "Destructing thread state %p\n", this);
213215
};
214216

215217
inline PyGreenlet* borrow_current() const
@@ -730,8 +732,8 @@ g_switchstack(void)
730732
{
731733
fprintf(stderr, "g_switchstack: enter\n");
732734
int err;
733-
_GThreadState& state = g_thread_state_global;
734735
{ /* save state */
736+
_GThreadState& state = g_thread_state_global;
735737
PyGreenlet* current = state.borrow_current();
736738
PyThreadState* tstate = PyThreadState_GET();
737739
current->recursion_depth = tstate->recursion_depth;
@@ -766,6 +768,7 @@ fprintf(stderr, "g_switchstack: mark 1\n");
766768
err = slp_switch();
767769
fprintf(stderr, "g_switchstack: mark 2\n");
768770
if (err < 0) { /* error */
771+
_GThreadState& state = g_thread_state_global;
769772
PyGreenlet* current = state.borrow_current();
770773
current->top_frame = NULL;
771774
#if GREENLET_PY37
@@ -782,6 +785,7 @@ fprintf(stderr, "g_switchstack: mark 2\n");
782785
else {
783786
fprintf(stderr, "g_switchstack: mark 3\n");
784787
// XXX: The ownership rules can be simplified here.
788+
_GThreadState& state = g_thread_state_global;
785789
PyGreenlet* target = state.borrow_target();
786790
PyGreenlet* origin = state.borrow_current();
787791
PyThreadState* tstate = PyThreadState_GET();
@@ -1814,11 +1818,15 @@ static int
18141818
green_setcontext(PyGreenlet* self, PyObject* nctx, void* c)
18151819
{
18161820
#if GREENLET_PY37
1817-
PyThreadState* tstate;
1818-
PyObject* octx = NULL;
1821+
/* XXX: Should not be necessary, we don't access the current greenlet
1822+
other than to compare it to ourself and its fine if that's null.
1823+
*/
1824+
/*
18191825
if (!STATE_OK) {
18201826
return -1;
18211827
}
1828+
*/
1829+
fprintf(stderr, "green_setcontext: enter\n");
18221830
if (nctx == NULL) {
18231831
PyErr_SetString(PyExc_AttributeError, "can't delete attribute");
18241832
return -1;
@@ -1833,11 +1841,16 @@ green_setcontext(PyGreenlet* self, PyObject* nctx, void* c)
18331841
"contextvars.Context or None");
18341842
return -1;
18351843
}
1836-
tstate = PyThreadState_GET();
1844+
fprintf(stderr, "green_setcontext: mark 1\n");
1845+
PyThreadState* tstate = PyThreadState_GET();
1846+
PyObject* octx = NULL;
1847+
18371848
if (PyGreenlet_ACTIVE(self) && self->top_frame == NULL) {
18381849
/* Currently running greenlet: context is stored in the thread state,
18391850
not the greenlet object. */
1851+
fprintf(stderr, "green_setcontext: mark 2 %p\n", &g_thread_state_global);
18401852
if (g_thread_state_global.is_current(self)) {
1853+
fprintf(stderr, "green_setcontext: mark 3\n");
18411854
octx = tstate->context;
18421855
tstate->context = nctx;
18431856
tstate->context_ver++;
@@ -1851,7 +1864,8 @@ green_setcontext(PyGreenlet* self, PyObject* nctx, void* c)
18511864
}
18521865
}
18531866
else {
1854-
/* Greenlet is not running: just set context. */
1867+
/* Greenlet is not running: just set context. Note that the
1868+
greenlet may be dead.*/
18551869
octx = self->context;
18561870
self->context = nctx;
18571871
Py_XINCREF(nctx);

0 commit comments

Comments
 (0)