mirror of https://github.com/python/cpython
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:
parent
82225b7737
commit
025c347d61
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue