From d8cba5d16f1333fd625726fc72e66afbd45b8d00 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Tue, 3 Jul 2018 13:47:22 -0600 Subject: [PATCH] bpo-24596: Decref module in PyRun_SimpleFileExFlags() on SystemExit (GH-7918) PyErr_Print() will not return when the exception is a SystemExit, so decref the __main__ module object in that case. --- Lib/test/test_gc.py | 17 ++++++++++++++++- .../2018-06-25-16-54-05.bpo-24596.Rkwova.rst | 2 ++ Python/pythonrun.c | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-06-25-16-54-05.bpo-24596.Rkwova.rst diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 904fc7d88c0..8d806db3ba5 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,7 +1,7 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, strip_python_stderr, cpython_only, start_threads, - temp_dir, requires_type_collecting) + temp_dir, requires_type_collecting, TESTFN, unlink) from test.support.script_helper import assert_python_ok, make_script import sys @@ -708,6 +708,21 @@ class GCTests(unittest.TestCase): rc, out, err = assert_python_ok('-c', code) self.assertEqual(out.strip(), b'__del__ called') + @requires_type_collecting + def test_global_del_SystemExit(self): + code = """if 1: + class ClassWithDel: + def __del__(self): + print('__del__ called') + a = ClassWithDel() + a.link = a + raise SystemExit(0)""" + self.addCleanup(unlink, TESTFN) + with open(TESTFN, 'w') as script: + script.write(code) + rc, out, err = assert_python_ok(TESTFN) + self.assertEqual(out.strip(), b'__del__ called') + def test_get_stats(self): stats = gc.get_stats() self.assertEqual(len(stats), 3) diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-06-25-16-54-05.bpo-24596.Rkwova.rst b/Misc/NEWS.d/next/Core and Builtins/2018-06-25-16-54-05.bpo-24596.Rkwova.rst new file mode 100644 index 00000000000..1b33fd4a44d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-06-25-16-54-05.bpo-24596.Rkwova.rst @@ -0,0 +1,2 @@ +Decref the module object in :c:func:`PyRun_SimpleFileExFlags` before calling +:c:func:`PyErr_Print()`. Patch by Zackery Spytz. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5cf7c33c93a..bcd1ca931d0 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -431,6 +431,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, } flush_io(); if (v == NULL) { + Py_CLEAR(m); PyErr_Print(); goto done; } @@ -439,7 +440,7 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); - Py_DECREF(m); + Py_XDECREF(m); return ret; }