From 0e8d520a38c902cc277fd576447dd11638a07237 2013-09-23 22:50:16 From: Thomas Kluyver Date: 2013-09-23 22:50:16 Subject: [PATCH] Test process exit codes with terminating signal --- diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py index a9764d8..3bdf2db 100644 --- a/IPython/core/tests/test_interactiveshell.py +++ b/IPython/core/tests/test_interactiveshell.py @@ -22,6 +22,7 @@ Authors # stdlib import ast import os +import signal import shutil import sys import tempfile @@ -425,26 +426,48 @@ class TestSafeExecfileNonAsciiPath(unittest.TestCase): """ ip.safe_execfile(self.fname, {}, raise_exceptions=True) +class ExitCodeChecks(tt.TempFileMixin): + def test_exit_code_ok(self): + self.system('exit 0') + self.assertEqual(ip.user_ns['_exit_code'], 0) + + def test_exit_code_error(self): + self.system('exit 1') + self.assertEqual(ip.user_ns['_exit_code'], 1) + + @skipif(not hasattr(signal, 'SIGALRM')) + def test_exit_code_signal(self): + self.mktmp("import signal, time\n" + "signal.setitimer(signal.ITIMER_REAL, 0.1)\n" + "time.sleep(1)\n") + self.system("%s %s" % (sys.executable, self.fname)) + self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM) + +class TestSystemRaw(unittest.TestCase, ExitCodeChecks): + system = ip.system_raw -class TestSystemRaw(unittest.TestCase): @onlyif_unicode_paths def test_1(self): """Test system_raw with non-ascii cmd """ - cmd = ur'''python -c "'åäö'" ''' + cmd = u'''python -c "'åäö'" ''' ip.system_raw(cmd) - - def test_exit_code(self): - """Test that the exit code is parsed correctly.""" - ip.system_raw('exit 1') - self.assertEqual(ip.user_ns['_exit_code'], 1) -class TestSystemPiped(unittest.TestCase): - # TODO: Exit codes are currently ignored on Windows. +# TODO: Exit codes are currently ignored on Windows. +class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks): + system = ip.system_piped + @skip_win32 - def test_exit_code(self): - ip.system_piped('exit 1') - self.assertEqual(ip.user_ns['_exit_code'], 1) + def test_exit_code_ok(self): + ExitCodeChecks.test_exit_code_ok(self) + + @skip_win32 + def test_exit_code_error(self): + ExitCodeChecks.test_exit_code_error(self) + + @skip_win32 + def test_exit_code_signal(self): + ExitCodeChecks.test_exit_code_signal(self) class TestModules(unittest.TestCase, tt.TempFileMixin): def test_extraneous_loads(self): diff --git a/IPython/utils/_process_posix.py b/IPython/utils/_process_posix.py index bb35225..d6d53ef 100644 --- a/IPython/utils/_process_posix.py +++ b/IPython/utils/_process_posix.py @@ -187,9 +187,9 @@ class ProcessHandler(object): # We follow the subprocess pattern, returning either the exit status # as a positive number, or the terminating signal as a negative - # number - if child.signalstatus is not None: - return -child.signalstatus + # number. sh returns 128+n for signals + if child.exitstatus > 128: + return -(child.exitstatus - 128) return child.exitstatus