Fix exit of subprocess in case it was terminated by signal

If child process of rootwrap is terminated by signal, exit code should
be 128 + N, where N is number of signal. According [1]
subprocess.Popen.returncode returns -N. sys.exit interprets negative
signed byte as unsigned thus original exit code is 256 - N instead of
128 + N.

[1]
https://docs.python.org/2/library/subprocess.html#subprocess.Popen.returncode

Change-Id: I43b4c959a98f8f620466c77de4cd5b724b09e5a8
Closes-Bug: #1364822
This commit is contained in:
Jakub Libosvar 2014-09-03 10:34:57 +02:00
parent aaf1869cc4
commit 56e9cb5b07
2 changed files with 22 additions and 2 deletions

View File

@ -44,6 +44,7 @@ RC_UNAUTHORIZED = 99
RC_NOCOMMAND = 98
RC_BADCONFIG = 97
RC_NOEXECFOUND = 96
SIGNAL_BASE = 128
def _exit_error(execname, message, errorcode, log=True):
@ -106,8 +107,11 @@ def run_one_command(execname, config, filters, userargs):
stdin=sys.stdin,
stdout=sys.stdout,
stderr=sys.stderr)
obj.wait()
sys.exit(obj.returncode)
returncode = obj.wait()
# Fix returncode of Popen
if returncode < 0:
returncode = SIGNAL_BASE - returncode
sys.exit(returncode)
except wrapper.FilterMatchNotExecutable as exc:
msg = ("Executable not found: %s (filter match = %s)"

View File

@ -23,6 +23,7 @@ import mock
from six import moves
import testtools
from oslo.rootwrap import cmd
from oslo.rootwrap import filters
from oslo.rootwrap import wrapper
@ -567,3 +568,18 @@ class PathFilterTestCase(testtools.TestCase):
os.path.realpath(self.TRAVERSAL_SYMLINK_WITHIN_DIR)]
self.assertEqual(expected, self.f.get_command(args))
class RunOneCommandTestCase(testtools.TestCase):
def _test_returncode_helper(self, returncode, expected):
with mock.patch.object(wrapper, 'start_subprocess') as mock_start:
with mock.patch('sys.exit') as mock_exit:
mock_start.return_value.wait.return_value = returncode
cmd.run_one_command(None, mock.Mock(), None, None)
mock_exit.assert_called_once_with(expected)
def test_positive_returncode(self):
self._test_returncode_helper(1, 1)
def test_negative_returncode(self):
self._test_returncode_helper(-1, 129)