Fix self-subscription device proxy in asyncio servers

Closes #747 (closed)

Summary

When green Executor delegates a function to the thread pool (e.g. via loop.run_in_executor()), the pool thread has a different threading.get_ident() than the executor loop thread. If that function makes a nested Tango call e.g. subscribe_event registering a green_callback), get_global_executor() to find the correct executor: in_executor_context() returns False, the ident is absent from _THREAD_EXECUTORS, and the call falls back to wrong executor.

Solution

Wrap every delegated callback in a thin closure (_callback_with_executor) that writes self into a threading.local (_delegate_thread_local) before invoking the real function. get_global_executor() reads this thread-local as a last-resort fallback after the ident-based lookups.

Thread-locals are per-thread and overwritten unconditionally at the start of each delegated call, so the value is always correct for the currently executing work — including when the thread pool reuses threads across different executors.

Additions

Now Future executor also uses PyTangoThreadPoolExecutor, the same one, that Asyncio does.

Merge request reports

Loading