Valkka
1.6.1
OpenSource Video Management
|
ValkkaFS is using both cpp-to-python and python-to-cpp calls
This can get tricky, and care must be taken to avoid nasty deadlocks due to the Python Global Interpreter Lock (GIL)
The cpp part of the code can decide to call some python code, that has been defined in the main thread Python part. This is done by the cpp code "autonomously" and is not initiated from the python side. (*)
Python part might evoke some cpp code. (**)
Special care must be taken with "callback cascades" that start from cpp and end up back to the cpp side again.
The acquisition and release of GIL is illustrated in the following graph.
(*) = callback from cpp to Python (**) = callback from Python to cpp | = the instance holding the GIL DEADLOCK = example deadlock situations A program using both (*) and (**) callbacks: main thread (Python) cpp thread | | | | acquire GIL (*) | - call python method, defined at main thread | release GIL | | | | acquire GIL (*) | - call python method, defined at main thread | - that python method might call cpp code which tries to acquire GIL => DEADLOCK! | release GIL | | | call swig-wrapped | cpp method (**) do not acquire GIL | as it's being hold by the main thread | return | | acquire GIL (*) | - call python method, defined at main thread | release GIL
main thread (Python) ValkkaFSWriterThread | | | acquire GIL | - call ValkkaFSWriterThread::pyfunc | - In the python side, this is set to valkka.api2.valkkafs.new_block_cb__ | - .. which in turn continues the callback-cascade into ValkkaFS::setArrayCall | release GIL | | | requestStopCall requestStopCall (cpp side) | (python side) - sends message to thread's message queue | - returns immediately | exits thread's running loop | waitStopCall preJoin | => saveCurrentBlock | => valkkaFS::writeBlock | - should not acquire GIL as this has been | requested from the python side | thread join & exit -------------------------------------------------- | CacheStream::run | pyfunc => valkka.api2.ValkkaFSManager.timeCallback__(mstime) => valkka.api2.ValkkaFSManager.stop() => ValkkaFSWriterThread::stopStreamsCall() # this makes any sense? - it's ok to call other thread's functions, as long as they don't return the callback chain to python