Skip to content

Commit 543df99

Browse files
committed
pythongh-99633: _contextvars: Enter the thread's initial context
No public API provides access to the current context yet (only a new copy), however: * This is good defensive practice. * This improves code readability. * Context watchers are now notified about the initial context. * A planned future commit will make it possible for users to access the thread's initial context object. Without this change, users would be able to enter the context a second time, causing a cycle in the context stack.
1 parent 11c500b commit 543df99

1 file changed

Lines changed: 13 additions & 9 deletions

File tree

‎Python/context.c‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ static inline void
187187
context_switched(PyThreadState *ts)
188188
{
189189
ts->context_ver++;
190-
// ts->context is used instead of context_get() because context_get() might
191-
// throw if ts->context is NULL.
190+
// ts->context is used instead of context_get() because if ts->context is
191+
// NULL, context_get() will either call context_switched -- causing a
192+
// double notification -- or throw.
192193
notify_context_watchers(ts, Py_CONTEXT_SWITCHED, ts->context);
193194
}
194195

@@ -475,15 +476,18 @@ context_get(void)
475476
{
476477
PyThreadState *ts = _PyThreadState_GET();
477478
assert(ts != NULL);
478-
PyContext *current_ctx = (PyContext *)ts->context;
479-
if (current_ctx == NULL) {
480-
current_ctx = context_new_empty();
481-
if (current_ctx == NULL) {
482-
return NULL;
479+
if (ts->context == NULL) {
480+
PyContext *ctx = context_new_empty();
481+
if (ctx != NULL && _PyContext_Enter(ts, ctx)) {
482+
Py_UNREACHABLE();
483483
}
484-
ts->context = (PyObject *)current_ctx;
484+
assert(ts->context == (PyObject *)ctx);
485+
Py_CLEAR(ctx); // _PyContext_Enter created its own ref.
485486
}
486-
return current_ctx;
487+
// The current context may be NULL if the above context_new_empty() call
488+
// failed.
489+
assert(ts->context == NULL || PyContext_CheckExact(ts->context));
490+
return (PyContext *)ts->context;
487491
}
488492

489493
static int

0 commit comments

Comments
 (0)