Merge "processutils: ensure on_completion callback is always called"

This commit is contained in:
Jenkins 2015-07-06 21:22:17 +00:00 committed by Gerrit Code Review
commit 7243f58810
2 changed files with 28 additions and 8 deletions
oslo_concurrency

@ -239,15 +239,16 @@ def execute(*cmd, **kwargs):
if on_execute:
on_execute(obj)
result = obj.communicate(process_input)
try:
result = obj.communicate(process_input)
obj.stdin.close() # pylint: disable=E1101
_returncode = obj.returncode # pylint: disable=E1101
LOG.log(loglevel, 'CMD "%s" returned: %s in %0.3fs',
sanitized_cmd, _returncode, watch.elapsed())
if on_completion:
on_completion(obj)
obj.stdin.close() # pylint: disable=E1101
_returncode = obj.returncode # pylint: disable=E1101
LOG.log(loglevel, 'CMD "%s" returned: %s in %0.3fs',
sanitized_cmd, _returncode, watch.elapsed())
finally:
if on_completion:
on_completion(obj)
if not ignore_exit_code and _returncode not in check_exit_code:
(stdout, stderr) = result

@ -20,6 +20,7 @@ import logging
import multiprocessing
import os
import stat
import subprocess
import sys
import tempfile
@ -78,6 +79,24 @@ class UtilsTest(test_base.BaseTestCase):
self.assertEqual(1, on_execute_callback.call_count)
self.assertEqual(1, on_completion_callback.call_count)
@mock.patch.object(subprocess.Popen, "communicate")
def test_execute_with_callback_and_errors(self, mock_comm):
on_execute_callback = mock.Mock()
on_completion_callback = mock.Mock()
def fake_communicate(*args):
raise IOError("Broken pipe")
mock_comm.side_effect = fake_communicate
self.assertRaises(IOError,
processutils.execute,
"/bin/true",
on_execute=on_execute_callback,
on_completion=on_completion_callback)
self.assertEqual(1, on_execute_callback.call_count)
self.assertEqual(1, on_completion_callback.call_count)
class ProcessExecutionErrorTest(test_base.BaseTestCase):