Skip to content

Notify context watchers when switching greenlets on Python 3.14+ #531

Description

@florentinl

Disclaimer: I work for Datadog and am interested in this feature in the context of dd-trace-py, our Python instrumentation library.

Summary

Python 3.14 added support for observing contextvars.Context switches through the Py_CONTEXT_SWITCHED event. Extension authors can register callbacks for this event using PyContext_AddWatcher.

It would be useful for a greenlet switch to trigger these watchers whenever resuming the target greenlet changes the current Context. This would provide a generic observability mechanism shared with asyncio and other parts of the Python ecosystem.

This is directly relevant to gevent: gevent.Greenlet subclasses greenlet.greenlet, and switching to its hub ultimately calls the underlying greenlet.switch() implementation. Implementing this in greenlet itself would therefore cover gevent without requiring a gevent-specific hook, while also benefiting other greenlet users.

Current behavior

Before switching, greenlet saves PyThreadState.context. When the target greenlet resumes, it restores that pointer directly and increments context_ver to invalidate the context variable cache.

In CPython, watcher notification is performed by the internal context_switched() helper. That helper is reached through PyContext_Enter and PyContext_Exit, but not when PyThreadState.context is changed directly.

As a result, greenlet correctly restores ContextVar values, but registered context watchers are not notified of the switch.

Design considerations

The only realistic approach I see is to push for exposing a new CPython API to trigger arbitrarily the interpreter registered watchers.
Or have an API to swap a context on PyThreadState which would handle the context_ver bump and the watcher invocations itself.

Would you be interested to support the feature, if such an API existed ?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions