Issue #1402: PyInterpreterState_Clear() may still invoke user code

(in deallocation of running threads, for example), so the PyGILState_Release()
function must still be functional.
On the other hand, _PyGILState_Fini() only frees memory, and can be called later.

Backport candidate, but only after some experts comment on it.
This commit is contained in:
Amaury Forgeot d'Arc 2007-11-29 23:35:25 +00:00
parent 82225b7737
commit 025c347d61
2 changed files with 39 additions and 5 deletions

View File

@ -202,6 +202,40 @@ class ThreadTests(unittest.TestCase):
t.join() t.join()
# else the thread is still running, and we have no way to kill it # else the thread is still running, and we have no way to kill it
def test_finalize_runnning_thread(self):
# Issue 1402: the PyGILState_Ensure / _Release functions may be called
# very late on python exit: on deallocation of a running thread for
# example.
try:
import ctypes
except ImportError:
if verbose:
print("test_finalize_with_runnning_thread can't import ctypes")
return # can't do anything
import subprocess
rc = subprocess.call([sys.executable, "-c", """if 1:
import ctypes, sys, time, thread
# Module globals are cleared before __del__ is run
# So we save the functions in class dict
class C:
ensure = ctypes.pythonapi.PyGILState_Ensure
release = ctypes.pythonapi.PyGILState_Release
def __del__(self):
state = self.ensure()
self.release(state)
def waitingThread():
x = C()
time.sleep(100)
thread.start_new_thread(waitingThread, ())
time.sleep(1) # be sure the other thread is waiting
sys.exit(42)
"""])
self.assertEqual(rc, 42)
class ThreadingExceptionTests(unittest.TestCase): class ThreadingExceptionTests(unittest.TestCase):
# A RuntimeError should be raised if Thread.start() is called # A RuntimeError should be raised if Thread.start() is called
# multiple times. # multiple times.

View File

@ -437,11 +437,6 @@ Py_Finalize(void)
_Py_PrintReferences(stderr); _Py_PrintReferences(stderr);
#endif /* Py_TRACE_REFS */ #endif /* Py_TRACE_REFS */
/* Cleanup auto-thread-state */
#ifdef WITH_THREAD
_PyGILState_Fini();
#endif /* WITH_THREAD */
/* Clear interpreter state */ /* Clear interpreter state */
PyInterpreterState_Clear(interp); PyInterpreterState_Clear(interp);
@ -453,6 +448,11 @@ Py_Finalize(void)
_PyExc_Fini(); _PyExc_Fini();
/* Cleanup auto-thread-state */
#ifdef WITH_THREAD
_PyGILState_Fini();
#endif /* WITH_THREAD */
/* Delete current thread */ /* Delete current thread */
PyThreadState_Swap(NULL); PyThreadState_Swap(NULL);
PyInterpreterState_Delete(interp); PyInterpreterState_Delete(interp);