Skip to content

symfonic.kernel.contracts.run_callbacks

run_callbacks

The lineage a loop callback keeps from the code that scheduled it.

loop.call_soon(cb, context=contextvars.Context()) inside a kernel run -- or from a task spawned with a stripped context -- runs cb in no task with no lineage in context, so a task it creates and a run that task issues would start as roots and launder what the scheduler was handed after a forget (CORE-199). asyncio has no hook where a callback is scheduled, so the kernel shadows the running loop's scheduling methods on the loop instance: call_soon, call_soon_threadsafe, call_later and call_at. The shadow resolves the scheduler's origin -- its lineage, as the task factory resolves it, or a task the factory never saw, which the census resolves only if the callback builds a task or issues a run -- and, if there is one, hands it to the callback for exactly its call (run_spawn); the callback still runs in the context it was given, so no other context variable reaches it. A scheduler with no lineage hands nothing on, so an unrelated request's callbacks -- a server's per-connection ones -- stay roots.

A callback bound to a future or task (a task's step, a future's set_result) is passed through: a task resolves its own record, never the callback's. A done-callback is scheduled by the code completing its future, so it is handed that code's lineage.

Measured to carry on CPython 3.12's selector loop and uvloop 0.22.1: both take the instance attribute, and user code and C tasks call it. A loop that refuses it carries nothing, so the kernel refuses every run there, typed, before the run starts (run_spawn): the shadows are installed all or none, the methods already shadowed are restored, and the loop is remembered so a later run refuses too. Not covered: a callback scheduled through a loop's internal path (a transport's protocol callbacks), work on another thread, an explicit executor or another process (run_spawn).

called_lineage

called_lineage() -> Any

The origin of the code that scheduled the callback this thread runs, if any.

Source code in src/symfonic/kernel/contracts/run_callbacks.py
def called_lineage() -> Any:
    """The origin of the code that scheduled the callback this thread runs, if any."""
    return getattr(_CALLED, "lineage", None)

track_callbacks

track_callbacks(loop: Any, resolve: Callable[[], Any]) -> bool

Shadow all of loop's scheduling methods, or none; whether the loop carries.

Source code in src/symfonic/kernel/contracts/run_callbacks.py
def track_callbacks(loop: Any, resolve: Callable[[], Any]) -> bool:
    """Shadow all of ``loop``'s scheduling methods, or none; whether the loop carries."""
    if _refused(loop):
        return False
    own = getattr(loop, "__dict__", {})
    installed: list[tuple[str, Any]] = []
    for name, at in _SCHEDULERS:
        if type(own.get(name)) is _Carrying:
            continue
        prior = own.get(name, _ABSENT)
        try:
            setattr(loop, name, _Carrying(getattr(loop, name), at, resolve))
            if type(getattr(loop, name, None)) is not _Carrying:
                raise AttributeError(name)  # accepted, but not what a caller reaches
        except (AttributeError, TypeError):
            _restore(loop, installed + [(name, prior)])
            _refuse(loop)
            return False
        installed.append((name, prior))
    return True