[Python-checkins] CVS: python/dist/src/Modules posixmodule.c,2.166,2.167

Tim Peters python-dev@python.org
Thu, 31 Aug 2000 23:51:28 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory slayer.i.sourceforge.net:/tmp/cvs-serv23159/python/dist/src/modules

Modified Files:
	posixmodule.c 
Log Message:
Fix test_popen2 on Windows, recently broken by changes to the dict(!)
implementation.  You don't want to know.  I've asked Guido to give this
a critical review (we agreed on the approach, but the implementation
proved more ... interesting ... than anticipated).  This will almost
certainly be the highlight of Mark Hammond's day <wink>.


Index: posixmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v
retrieving revision 2.166
retrieving revision 2.167
diff -C2 -r2.166 -r2.167
*** posixmodule.c	2000/08/15 18:52:33	2.166
--- posixmodule.c	2000/09/01 06:51:24	2.167
***************
*** 2686,2689 ****
--- 2686,2704 ----
   * 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)
  {
***************
*** 2693,2697 ****
  	PyObject *procObj, *hProcessObj, *intObj, *fileObj;
  	long file_count;
!    
  	/* Close the file handle first, to ensure it can't block the
  	 * child from exiting if it's the last handle.
--- 2708,2716 ----
  	PyObject *procObj, *hProcessObj, *intObj, *fileObj;
  	long file_count;
! #ifdef WITH_THREAD
! 	PyInterpreterState* pInterpreterState;
! 	PyThreadState* pThreadState;
! #endif
! 
  	/* Close the file handle first, to ensure it can't block the
  	 * child from exiting if it's the last handle.
***************
*** 2699,2702 ****
--- 2718,2746 ----
  	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 &&
***************
*** 2755,2758 ****
--- 2799,2814 ----
  		Py_XDECREF(fileObj);
  	} /* if _PyPopenProcs */
+ 
+ #ifdef WITH_THREAD
+ 	/* Tear down the thread & interpreter states.
+ 	 * Note that interpreter state clear & delete functions automatically
+ 	 * call the thread & clear 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;