PyThreadState_Swap difference in 2.3.2?
Mark Hammond
mhammond at skippinet.com.au
Mon Dec 15 19:07:48 EST 2003
vincent wehren wrote:
> "Paul Miller" <paul at fxtech.com> schrieb im Newsbeitrag
> news:knbstvgsn3o3qmmtu975g8eb94rhpmae2o at 4ax.com...
> | I have a C++ application that uses multiple embedded Python interpreters.
> I
> | allocate multiple interpreters using Py_NewInterpreter, and switch between
> | them using PyThreadSate_Swap.
> |
> | In 2.2.2, this all worked fine.
> |
> | I just installed 2.3.2, but now the first time I call Py_NewInterpreter,
> it
> | bails out in PyThreadState_Swap, in the debug checking code, with:
> |
> | Py_FatalError("Invalid thread state for this thread");
> |
> | Has the interpreter/thread setup code changed since 2.2?
> |
> | To be complete, I set up with this:
> |
> | Py_Initialize();
> | PyThreadState *globalState = PyThreadState_Get();
> |
> | // allocate new interpreter
> | PyThreadState *interp = Py_NewInterpreter();
>
> The same thing stumped me too a couple of days ago (s.
> http://groups.google.nl/groups?q=PyNew_Interpreter&hl=nl&lr=&ie=UTF-8&oe=UTF-8&selm=braiu1%243r3%241%40news4.tilbu1.nb.home.nl&rnum=1 )
> with 2.3.3c1 (same applies 2.4a0 for that matter).
>
> Although I am sure the following snip in PyThreadState_Swap was put there
> for a reason,
> it would be great if someone could put some light on the matter....:
>
> /* It should not be possible for more than one thread state
> to be used for a thread. Check this the best we can in debug
> builds.
> */
> #if defined(Py_DEBUG) && defined(WITH_THREAD)
> if (new) {
> PyThreadState *check = PyGILState_GetThisThreadState();
> if (check && check != new)
> Py_FatalError("Invalid thread state for this thread");
> }
> #endif
Python stores information in the thread-state structure which is
specific to the thread - information such as the exception being
handled, the current recursion depth, etc.
The assertion above is reporting the fact that 2 distinct ThreadState
objects are trying to be used on a single thread. The same thread for
which you are trying to create a thread-state already has such a state.
Earlier versions of Python made no attempt to detect this, but as far as
everyone can tell, was always an implicit assumption.
Unfortunately, much of this stuff has never been thought through
correctly. Trying to work with multiple InterpreterState objects is
also very difficult, and in some cases simply does not work, as not all
global variables are stored in an InterpreterState. Theoretically
though, this is probably what you want - if a different InterpreterState
is current, I would expect a ThreadState specific to the
InterpreterState could be used - but I doubt it works <wink>
The easy answer is to stop trying to create multiple interpreter states,
then use the PyGILState calls to manage your thread-state. These should
be 2 lines per function (rather than the many that exist now). If you
need to build in both pre 2.3 and 2.3+:
#if (PY_VERSION_HEX >= 0x02030000)
#define USE_GILSTATE
#endif
/* Then */
#ifdef USE_GILSTATE
PyGILState_State state = PyGILState_Ensure();
#else
20 lines of existing code
#endif
// your body, and at the end
#ifdef USE_GILSTATE
PyGILState_Release(state);
#else
existing code
#endif
Mark.
More information about the Python-list
mailing list