Test atexit shutdown mechanism in a subprocess (#4828)
* Test atexit shutdown mechanism in a subprocess
diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py
index 1d0b018..aa56388 100644
--- a/Lib/test/test_atexit.py
+++ b/Lib/test/test_atexit.py
@@ -3,6 +3,7 @@
import io
import atexit
from test import support
+from test.support import script_helper
### helpers
def h1():
@@ -152,6 +153,21 @@
atexit._run_exitfuncs()
self.assertEqual(l, [5])
+ def test_shutdown(self):
+ # Actually test the shutdown mechanism in a subprocess
+ code = """if 1:
+ import atexit
+
+ def f(msg):
+ print(msg)
+
+ atexit.register(f, "one")
+ atexit.register(f, "two")
+ """
+ res = script_helper.assert_python_ok("-c", code)
+ self.assertEqual(res.out.decode().splitlines(), ["two", "one"])
+ self.assertFalse(res.err)
+
@support.cpython_only
class SubinterpreterTest(unittest.TestCase):
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index fdb09d9..f284855 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2086,6 +2086,8 @@
/* For the atexit module. */
void _Py_PyAtExit(void (*func)(void))
{
+ /* Guard against API misuse (see bpo-17852) */
+ assert(_PyRuntime.pyexitfunc == NULL || _PyRuntime.pyexitfunc == func);
_PyRuntime.pyexitfunc = func;
}