| Graham Dumpleton 2006-05-20, 7:11 am |
|
On 20/05/2006, at 6:27 PM, Nicolas Lehuen wrote:
> OK, it seems that my last hypothesis was the good one : mod_python is
> doing things with thread states that are frowned upon by debug build.
> The tests are only performed in the debug build, so that's why we had
> no problem with the release build.
>
> The tests are found in pystate.c, in function PyThreadState_Swap (line
> 297 in the current trunk revision) :
>
> /* 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 (newts) {
> PyThreadState *check = PyGILState_GetThisThreadState();
> if (check && check->interp == newts->interp && check != newts)
> Py_FatalError("Invalid thread state for this thread");
> }
> #endif
>
> So it seems mod_python is trying to share the same thread state
> between multiple threads, which "should not be possible". If someone
> has an idea, please help me, because I'm not really up to date about
> thread state management, so I'll have to read a fair bit of
> documentation before understanding what's happening there.
For each request a new thread state is created.
That is, in get_interpreter() it does:
/* create thread state and acquire lock */
tstate = PyThreadState_New(idata->istate);
#ifdef WITH_THREAD
PyEval_AcquireThread(tstate);
#else
PyThreadState_Swap(tstate);
#endif
In this case, PyThreadState_Swap() isn't called when HAVE_THREAD is
defined, which is only time your check is done.
The problem seems to related to where PyThreadState_Swap() function is
always called in make_interpreter() and PythonChildInitHandler().
Will have to track down what that call is doing at those points.
Maybe those
calls should be:
#ifdef WITH_THREAD
PyEval_ReleaseThread(tstate);
#else
PyThreadState_Swap(NULL);
#endif
Graham
[vbcol=seagreen]
> Regards,
> Nicolas
>
> 2006/5/20, Nicolas Lehuen <nicolas@lehuen.com>:
|