Py_NewInterpreter(), is this a bug in the python core?

freesteel zabaione at uk2.net
Mon Jul 10 12:18:13 EDT 2006


/*
Is this a bug in Py_NewInterpreter?

The function below "MyThread" is instantiated from a windows worker
thread, but I don't
think that is relevant.
(I can try this on a linux box, but I would have to compile a python
library with debugging
enabled.)

The following code fragment throws an exception in a debug version of
python:
*/

UINT MyThread(LPVOID lpParam)
{
	{
		cs.Lock(); // this is a CCriticalSection lock
		if (!Py_IsInitialized())
		{
			Py_Initialize();
			PyEval_InitThreads();

			// global pointer to the main PyThreadState object
			mainThreadState = PyThreadState_Get();
			PyEval_ReleaseLock();
		}
		cs.Unlock();
	}

	ASSERT(Py_IsInitialized());
	ASSERT(PyEval_ThreadsInitialized());
	ASSERT(mainThreadState);
	threadnum++;

	// get the global lock
	PyEval_AcquireLock();
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure(); // Is tis necessary?


	PyThreadState_Swap(mainThreadState);
	PyThreadState* nts = Py_NewInterpreter();

/*

The exception is thrown inside the above function call:
This statement tries to swap the new threadstate 'tstate' with the
current one
	save_tstate = PyThreadState_Swap(tstate);

Inside PyThreadState_Swap the code uses another way
'PyGILState_GetThisThreadState()' to find the current thread state and
compares this with the newly set thread state.
Naturally you would expect the two to be equal but that test fails:
#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

The variable 'check' looks as if it is the 'previous' thread state, as
if changing the thread state
is not been done properly. Py_FatalError is called and that's the end.

Is there a mistake in my code, or is there something wrong in how
Py_NewInterpreter is implemented?


Thanks

Martin

PS: Below the rest of my simple test worker thread function.
*/




	ASSERT(nts == PyThreadState_Get());

	// lock (already locked) - swap in thread state - swap out thread
state - unlock

	init_testclass();


	int ret = 0;

	ret = PyRun_SimpleString("import sys");
	ret = PyRun_SimpleString("class redir:\n  def __init__(self, id):\n
self.id = id\n  def write(self, s):\n    f = open('stdoutputs_%s.txt' %
self.id, 'a')\n    f.write('%s: %s' % (self.id, s))\n    f.close()\n");
	char str[100];
	sprintf(str,"r = redir('0x%x')", &nts);
	ret = PyRun_SimpleString(str);
	ret = PyRun_SimpleString("sys.stderr = r");
	sprintf(str,"s = redir('0x%x')", &nts);
	ret = PyRun_SimpleString(str);
	ret = PyRun_SimpleString("sys.stdout = s");

	ret = PyRun_SimpleString("import testclass");
	ret = PyRun_SimpleString("t = testclass.testclass()");
	sprintf(str,"print 't = ', t ");
	ret = PyRun_SimpleString(str);
	ret = PyRun_SimpleString("print t.run(10)");


	Py_EndInterpreter(nts);
    PyGILState_Release(gstate);
	PyEval_ReleaseLock();

	return 0;
}




More information about the Python-list mailing list