-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG]: Cannot import pybind11-based python module from subinterpreter #4245
Comments
I can confirm that I can reproduce this bug, investigating now. |
The cause of the problem is that pybind11 is using PyGILState_Ensure and PyGILState_Release, which explicitly doesn't support sub interpreters. We would need to migrate pybind11 over to PyEval_SaveThread and PyEval_RestoreThread in order to add sub interpreter support. |
@rwgk This may affect your SimpleGIL refactor. |
At first glance: none of the 7 RAII types in the reproducer follows the rule-of-3 (or rule-of-5), which is bug prone. @mdorier did you rule out already that that's not an issue (in the reproducer or the original code)? The first thing I'd do is make those types safe. Even if it turns out that there was no problem, sooner or later someone will fall off a cliff because of the missing guard rails, especially when debugging. |
@rwgk It doesn't matter if his code is buggy or not since we are using an API which itself declares in the Python docs that it shouldn't work with sub-interpreters.
https://docs.python.org/3/c-api/init.html#non-python-created-threads |
I copied this code from an example found online about how to use subinterpreters. This is not the code in my codebase (my code base is in C, doing "manually" the kind of locking/unlocking that the code above dose with RAII). It was just simpler for a reproducer. However just looking at it, none of the variables involved are moved or copied, so I'm pretty sure this is not the problem. |
Thanks for the pointer! I'm totally not familiar with this. IIUC that basically makes this bug a feature request. Sorry small rant, to explain where I'm coming from, my personal opinion not reflecting anything official: I believe threads are one of the worst aberrations of software engineering, and subinterpreters, too, creating more problems than they solve. Like a junkie finds joy in a shot even though it is destroying his life, there seems to be a lot of joy in short-sighted optimizations. With that said: If we want to support subinterpreters, fine by me, but it looks like someone will need to sink in a significant amount of time, especially because we'd need full testing: anything that's not tested is likely to be broken one way or another sooner or later. Full testing looks tricky: highly platform dependent, the combination of fork, threads, subinterpreters is a bit of a combinatorial explosion of situations to test. |
It would be much better to tell people |
Yeah, this is pretty much a feature request and feels low priority given that sub-interpreters are a pretty niche feature.
In theory this should be trivial. assert(PyInterpreterState_Main() == PyThreadState_GetInterpreter()). I might try a simple PR this weekend. |
Awesome, thanks! |
What exactly do you have in mind? From my end:
Side remarks:
|
I meant mostly providing a path for embedding sub-interpreters in pybind11 without having to use the underlying Python C-API. For example, it could be another RAII interface (e.g., |
Sounds good. |
Required prerequisites
Problem description
I have a code that uses Python's C API (not pybind11) and creates subinterpreters in which to run code. The code works fine, apart from when a subinterpreter tries to import a python package that is based on pybind11: in such a situation, it hangs. Importing other, non-pybind11 packages, works fine.
Reproducible example code
(main.cpp) Code that runs subinterpreters with Python C API:
(module.cpp) Code of a pybind11-based module
(CMakeLists.txt) CMake file to build the project
The text was updated successfully, but these errors were encountered: