Python embedding with threads -- avoiding deadlocks?

2024/11/17 14:50:11

Is there any way to embed python, allow callbacks from python to C++, allowing the Pythhon code to spawn threads, and avoiding deadlocks?

The problem is this:

  • To call into Python, I need to hold the GIL. Typically, I do this by getting the main thread state when I first create the interpreter, and then using PyEval_RestoreThread() to take the GIL and swap in the thread state before I call into Python.

  • When called from Python, I may need to access some protected resources that are protected by a separate critical section in my host. This means that Python will hold the GIL (potentially from some other thread than I initially called into), and then attempt to acquire my protection lock.

  • When calling into Python, I may need to hold the same locks, because I may be iterating over some collection of objects, for example.

The problem is that even if I hold the GIL when I call into Python, Python may give it up, give it to another thread, and then have that thread call into my host, expecting to take the host locks. Meanwhile, the host may take the host locks, and the GIL lock, and call into Python. Deadlock ensues.

The problem here is that Python relinquishes the GIL to another thread while I've called into it. That's what it's expected to do, but it makes it impossible to sequence locking -- even if I first take GIL, then take my own lock, then call Python, Python will call into my system from another thread, expecting to take my own lock (because it un-sequenced the GIL by releasing it).

I can't really make the rest of my system use the GIL for all possible locks in the system -- and that wouldn't even work right, because Python may still release it to another thread.

I can't really guarantee that my host doesn't hold any locks when entering Python, either, because I'm not in control of all the code in the host.

So, is it just the case that this can't be done?

Answer

"When calling into Python, I may need to hold the same locks, because I may be iterating over some collection of objects, for example."

This often indicates that a single process with multiple threads isn't appropriate. Perhaps this is a situation where multiple processes -- each with a specific object from the collection -- makes more sense.

Independent process -- each with their own pool of threads -- may be easier to manage.

https://en.xdnf.cn/q/71177.html

Related Q&A

RuntimeError: Event loop is closed when using pytest-asyncio to test FastAPI routes

I received the errorRuntimeError: Event loop is closedeach time I try to make more than one async call inside my test. I already tried to use all other suggestions from other Stack Overflow posts to re…

Adjust threshold cros_val_score sklearn

There is a way to set the threshold cross_val_score sklearn?Ive trained a model, then I adjust the threshold to 0.22. The model in the following below :# Try with Threshold pred_proba = LGBM_Model.pre…

Efficiently insert multiple elements in a list (or another data structure) keeping their order

I have a list of items that should be inserted in a list-like data structure one after the other, and I have the indexes at which each item should be inserted. For example: items = [itemX, itemY, itemZ…

matplotlib versions =3 does not include a find()

I am running a very simple Python script: from tftb.generators import amgauss, fmlinI get this error: C:\Users\Anaconda3\envs\tf_gpu\lib\site-packages\tftb-0.0.1-py3.6.egg\tftb\processing\affine.py in …

How to fix Field defines a relation with the model auth.User, which has been swapped out

I am trying to change my user model to a custom one. I do not mind dropping my database and just using a new one, but when I try it to run makemigrations i get this errorbookings.Session.session_client…

Generate and parse Python code from C# application

I need to generate Python code to be more specific IronPyton. I also need to be able to parse the code and to load it into AST. I just started looking at some tools. I played with "Oslo" and …

An efficient way to calculate the mean of each column or row of non-zero elements

I have a numpy array for ratings given by users on movies. The rating is between 1 and 5, while 0 means that a user does not rate on a movie. I want to calculate the average rating of each movie, and t…

Selecting unique observations in a pandas data frame

I have a pandas data frame with a column uniqueid. I would like to remove all duplicates from the data frame based on this column, such that all remaining observations are unique.

GEdit/Python execution plugin?

Im just starting out learning python with GEdit plus various plugins as my IDE.Visual Studio/F# has a feature which permits the highlighting on a piece of text in the code window which then, on a keyp…

autoclass and instance attributes

According to the sphinx documentation, the .. autoattribute directive should be able to document instance attributes. However, if I do::.. currentmodule:: xml.etree.ElementTree.. autoclass:: ElementTre…