I have a c++ application that implements its own Python interpreter and console. The user can enter Python code into the console, and that text gets sent to another thread where I make calls to the Python C API to execute the instructions. This secondary thread is the only thread that ever directly calls the Python C API. This generally works fine. However, I'm running into a crash where a user is trying to use matplotlib via plt.show(block = False). This should open up the plot such that it doesn't block my main python thread. The error I get back in my IDE is:
Fatal Python error: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is relea sed (the current Python thread state is NULL)
Fatal Python error: PyEval_RestoreThread: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL) Python runtime state: initialized
Current thread 0x00002d80 (most recent call first):
Extension modules: numpy._core._multiarray_umath, numpy.linalg._umath_linalg, PIL._imaging, kiwisolver._cext, PIL._imagingmath, PIL._imagingtk (total: 6)
Note, calling plt.show(block = True) works fine.
I'm currently wrapping all of my Python C API calls with PyGILState_Ensure prior to the call, and then PyGILState_Release is afterwards. This doesn't seem to help, since the same exact problem arises if I do nothing to acquire the GIL. As far as documentation goes, I can't see why this doesn't work.
Any help would be much appreciated.
PyGILState_Releaseends up destroying the Python threadstate for that thread. I suspect Matplotlib has an event loop in the background that's trying to reacquire that destroyed state. You probably want to get the GIL once withPyGILState_Ensure, only release it at the end of your program, and usePyEval_SaveThreadbetween calls instead