Skip to content

Commit 68f8ec6

Browse files
make entering of context thread safe
1 parent b8d3fdd commit 68f8ec6

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

Python/context.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,20 @@ _PyContext_Enter(PyThreadState *ts, PyObject *octx)
195195
{
196196
ENSURE_Context(octx, -1)
197197
PyContext *ctx = (PyContext *)octx;
198+
#ifdef Py_GIL_DISABLED
199+
int already_entered = _Py_atomic_exchange_int(&ctx->ctx_entered, 1);
200+
#else
201+
int already_entered = ctx->ctx_entered;
202+
ctx->ctx_entered = 1;
203+
#endif
198204

199-
if (ctx->ctx_entered) {
205+
if (already_entered) {
200206
_PyErr_Format(ts, PyExc_RuntimeError,
201207
"cannot enter context: %R is already entered", ctx);
202208
return -1;
203209
}
204210

205211
ctx->ctx_prev = (PyContext *)ts->context; /* borrow */
206-
ctx->ctx_entered = 1;
207-
208212
ts->context = Py_NewRef(ctx);
209213
context_switched(ts);
210214
return 0;
@@ -225,8 +229,14 @@ _PyContext_Exit(PyThreadState *ts, PyObject *octx)
225229
{
226230
ENSURE_Context(octx, -1)
227231
PyContext *ctx = (PyContext *)octx;
232+
#ifdef Py_GIL_DISABLED
233+
int already_entered = _Py_atomic_exchange_int(&ctx->ctx_entered, 0);
234+
#else
235+
int already_entered = ctx->ctx_entered;
236+
ctx->ctx_entered = 0;
237+
#endif
228238

229-
if (!ctx->ctx_entered) {
239+
if (!already_entered) {
230240
PyErr_Format(PyExc_RuntimeError,
231241
"cannot exit context: %R has not been entered", ctx);
232242
return -1;
@@ -243,7 +253,6 @@ _PyContext_Exit(PyThreadState *ts, PyObject *octx)
243253
Py_SETREF(ts->context, (PyObject *)ctx->ctx_prev);
244254

245255
ctx->ctx_prev = NULL;
246-
ctx->ctx_entered = 0;
247256
context_switched(ts);
248257
return 0;
249258
}

0 commit comments

Comments
 (0)