fermi-ad / acsys-python

Python module to access the Fermilab Control System
MIT License
8 stars 4 forks source link

Allow Manual Closing of DAQ Context Manager Outside of the Context #50

Closed beauremus closed 1 year ago

beauremus commented 2 years ago

We need a way to manually close an AsyncContextManager outside of the context manager. For example, in a parent process that spawns data acquisition threads.

We recommended that a user store the context in parent memory and call .cancel() at a later time. This doesn't work for several reasons. First, DPMContext returns a DPM object, not a Context Manager and DPM doesn't implement a close method. Second, even if we change the API to return the manager as well, calling .aclose() or dpm._shutdown() results in RuntimeError: aclose(): asynchronous generator is already running.

rneswold commented 2 years ago

Found this: https://bugs.python.org/issue38559

The reason for that runtime error is that we have a thread inside a call to __anext__() and are trying to call __aclose__(). The async generator support isn't thread-safe enough to allow closing when another thread is using the state, so they throw this exception.

The discussion in that bug track mentions our exact use-case (where __anext__() calls await queue.get()) and their conclusion is that allowing the __aclose__() could cause the queue to get corrupted (!)

zongweiyuan commented 2 years ago

I like to try. first I need to repeat this situation.

rneswold commented 2 years ago

Thanks, Zongwei. I'm experimenting with something at the moment. Hopefully it's a solution.