CodecFork.generateVideoFramesLibav and generateVideoFramesGstreamer are async
generator functions, so their bodies -- including the call_later(10, timeoutExit)
that lets the worker kill itself -- do not run until the caller requests the first
frame. The PluginFork handle is discarded at handout in LibavGenerator and
GstreamerGenerator, so a worker that is handed a session but never iterated has no
watchdog and no reachable terminate(), and idles for the life of the plugin host.
aclose() on a never-started async generator returns without executing the body, so
even a consumer that closes the RPC proxy cannot trigger the self-destruct.
Make the two methods coroutines that return the inner generator. rpc.py does
await maybe_await(invoke(*args)) before serializing, so the async iterator proxy
seen by the caller is unchanged, but the watchdog is armed as soon as the fork is
committed to a session.
Also keep the PluginFork handle at the call sites and terminate it if the session
cannot be handed to the caller.
Fixes#2138
Claude-Session: https://claude.ai/code/session_018kjDzffi8VZKA1mn6nrGfo
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>