[Python-checkins] python/dist/src/Modules _testcapimodule.c,1.21,1.22 posixmodule.c,2.294,2.295

mhammond@users.sourceforge.net mhammond@users.sourceforge.net
Sat, 19 Apr 2003 08:42:20 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv30725/Modules

Modified Files:
	_testcapimodule.c posixmodule.c 
Log Message:
New PyGILState_ API - implements pep 311, from patch 684256.


Index: _testcapimodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** _testcapimodule.c	17 Apr 2003 18:55:25 -0000	1.21
--- _testcapimodule.c	19 Apr 2003 15:41:47 -0000	1.22
***************
*** 8,11 ****
--- 8,15 ----
  #include "Python.h"
  
+ #ifdef WITH_THREAD
+ #include "pythread.h"
+ #endif /* WITH_THREAD */
+ 
  static PyObject *TestError;	/* set to exception object in init */
  
***************
*** 536,539 ****
--- 540,583 ----
  }
  
+ #ifdef WITH_THREAD
+ 
+ void _make_call(void *callable)
+ {
+ 	PyObject *rc;
+ 	PyGILState_STATE s = PyGILState_Ensure();
+ 	rc = PyObject_CallFunction(callable, "");
+ 	Py_XDECREF(rc);
+ 	PyGILState_Release(s);
+ }
+ 
+ static PyObject *
+ test_thread_state(PyObject *self, PyObject *args)
+ {
+ 	PyObject *fn;
+ 	if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn))
+ 		return NULL;
+ 	/* Ensure Python is setup for threading */
+ 	PyEval_InitThreads();
+ 	/* Start a new thread for our callback. */
+ 	PyThread_start_new_thread( _make_call, fn);
+ 	/* Make the callback with the thread lock held by this thread */
+ 	_make_call(fn);
+ 	/* Do it all again, but this time with the thread-lock released */
+ 	Py_BEGIN_ALLOW_THREADS
+ 	_make_call(fn);
+ 	Py_END_ALLOW_THREADS
+ 	/* And once more with and without a thread
+ 	   XXX - should use a lock and work out exactly what we are trying 
+ 	   to test <wink> 
+ 	*/
+ 	Py_BEGIN_ALLOW_THREADS
+ 	PyThread_start_new_thread( _make_call, fn);
+ 	_make_call(fn);
+ 	Py_END_ALLOW_THREADS
+ 	Py_INCREF(Py_None);
+ 	return Py_None;
+ }
+ #endif
+ 
  static PyMethodDef TestMethods[] = {
  	{"raise_exception",	raise_exception,		 METH_VARARGS},
***************
*** 554,557 ****
--- 598,604 ----
  #ifdef Py_USING_UNICODE
  	{"test_u_code",		(PyCFunction)test_u_code,	 METH_NOARGS},
+ #endif
+ #ifdef WITH_THREAD
+ 	{"_test_thread_state", (PyCFunction)test_thread_state, METH_VARARGS},
  #endif
  	{NULL, NULL} /* sentinel */

Index: posixmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
retrieving revision 2.294
retrieving revision 2.295
diff -C2 -d -r2.294 -r2.295
*** posixmodule.c	29 Mar 2003 10:04:54 -0000	2.294
--- posixmodule.c	19 Apr 2003 15:41:47 -0000	2.295
***************
*** 4355,4374 ****
   * files to be closed in any order - it is always the close() of the
   * final handle that will return the exit code.
   */
  
-  /* RED_FLAG 31-Aug-2000 Tim
-   * This is always called (today!) between a pair of
-   * Py_BEGIN_ALLOW_THREADS/ Py_END_ALLOW_THREADS
-   * macros.  So the thread running this has no valid thread state, as
-   * far as Python is concerned.  However, this calls some Python API
-   * functions that cannot be called safely without a valid thread
-   * state, in particular PyDict_GetItem.
-   * As a temporary hack (although it may last for years ...), we
-   * *rely* on not having a valid thread state in this function, in
-   * order to create our own "from scratch".
-   * This will deadlock if _PyPclose is ever called by a thread
-   * holding the global lock.
-   */
- 
  static int _PyPclose(FILE *file)
  {
--- 4355,4363 ----
   * files to be closed in any order - it is always the close() of the
   * final handle that will return the exit code.
+  *
+  * NOTE: This function is currently called with the GIL released.
+  * hence we use the GILState API to manage our state.
   */
  
  static int _PyPclose(FILE *file)
  {
***************
*** 4379,4384 ****
  	long file_count;
  #ifdef WITH_THREAD
! 	PyInterpreterState* pInterpreterState;
! 	PyThreadState* pThreadState;
  #endif
  
--- 4368,4372 ----
  	long file_count;
  #ifdef WITH_THREAD
! 	PyGILState_STATE state;
  #endif
  
***************
*** 4387,4416 ****
  	 */
  	result = fclose(file);
- 
  #ifdef WITH_THREAD
! 	/* Bootstrap a valid thread state into existence. */
! 	pInterpreterState = PyInterpreterState_New();
! 	if (!pInterpreterState) {
! 		/* Well, we're hosed now!  We don't have a thread
! 		 * state, so can't call a nice error routine, or raise
! 		 * an exception.  Just die.
! 		 */
! 		 Py_FatalError("unable to allocate interpreter state "
! 		 	       "when closing popen object");
! 		 return -1;  /* unreachable */
! 	}
! 	pThreadState = PyThreadState_New(pInterpreterState);
! 	if (!pThreadState) {
! 		 Py_FatalError("unable to allocate thread state "
! 		 	       "when closing popen object");
! 		 return -1;  /* unreachable */
! 	}
! 	/* Grab the global lock.  Note that this will deadlock if the
! 	 * current thread already has the lock! (see RED_FLAG comments
! 	 * before this function)
! 	 */
! 	PyEval_RestoreThread(pThreadState);
  #endif
- 
  	if (_PyPopenProcs) {
  		if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
--- 4375,4381 ----
  	 */
  	result = fclose(file);
  #ifdef WITH_THREAD
! 	state = PyGILState_Ensure();
  #endif
  	if (_PyPopenProcs) {
  		if ((fileObj = PyLong_FromVoidPtr(file)) != NULL &&
***************
*** 4471,4485 ****
  
  #ifdef WITH_THREAD
! 	/* Tear down the thread & interpreter states.
! 	 * Note that interpreter state clear & delete functions automatically
! 	 * call the thread clear & delete functions, and indeed insist on
! 	 * doing that themselves.  The lock must be held during the clear, but
! 	 * need not be held during the delete.
! 	 */
! 	PyInterpreterState_Clear(pInterpreterState);
! 	PyEval_ReleaseThread(pThreadState);
! 	PyInterpreterState_Delete(pInterpreterState);
  #endif
- 
  	return result;
  }
--- 4436,4441 ----
  
  #ifdef WITH_THREAD
! 	PyGILState_Release(state);
  #endif
  	return result;
  }