From 9ed77358d618e4c65fbe5df67a87618be29fc391 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 4 Apr 2008 23:25:27 +0000 Subject: [PATCH] Issue2221: in Idle, exec('xx') raised a SystemError('error return without exception set') instead of the expected NameError This happens when sys.stdout is redirected to something that cannot flush(). the flush_io() function must be exception-neutral: don't raise, and don't clear exceptions. Next step: exec() is not supposed to flush sys.stdout... --- Lib/test/test_builtin.py | 11 +++++++++++ Python/pythonrun.c | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 111090c1ab0..7244aff8eff 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -448,6 +448,17 @@ class BuiltinTest(unittest.TestCase): del l['__builtins__'] self.assertEqual((g, l), ({'a': 1}, {'b': 2})) + def test_exec_redirected(self): + savestdout = sys.stdout + sys.stdout = None # Whatever that cannot flush() + try: + # Used to raise SystemError('error return without exception set') + exec('a') + except NameError: + pass + finally: + sys.stdout = savestdout + def test_filter(self): self.assertEqual(list(filter(lambda c: 'a' <= c <= 'z', 'Hello World')), list('elloorld')) self.assertEqual(list(filter(None, [1, 'hello', [], [3], '', None, 9, 0])), [1, 'hello', [3], 9]) diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 74e3430e972..3207fb8b817 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1467,6 +1467,11 @@ static void flush_io(void) { PyObject *f, *r; + PyObject *type, *value, *traceback; + + /* Save the current exception */ + PyErr_Fetch(&type, &value, &traceback); + f = PySys_GetObject("stderr"); if (f != NULL) { r = PyObject_CallMethod(f, "flush", ""); @@ -1483,6 +1488,8 @@ flush_io(void) else PyErr_Clear(); } + + PyErr_Restore(type, value, traceback); } static PyObject *