[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;