+# Copyright (c) 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
import os
import sys
import shlex
import shutil
import contextlib
import pprint
-import traceback
+import signal
from tempfile import TemporaryDirectory
self._runtime_log_aggregation = os.path.join(self.__runtime_log, "runtime.log")
self._run_command_count = 0
+ self._is_test_modules_loaded = False
self.special_env_variables = {"LTTNG_UST_DEBUG": "1",
- #"LTTNG_APP_SOCKET_TIMEOUT": "-1",
+ "LTTNG_APP_SOCKET_TIMEOUT": "-1",
#"LTTNG_UST_REGISTER_TIMEOUT": "-1",
"LTTNG_NETWORK_SOCKET_TIMEOUT": "-1"}
def add_project(self, project):
self.__projects.append(project)
+ def remove_project(self, project):
+ self.__projects.remove(project)
+
def subprocess_signal(self, subprocess_uuid, signal):
self.__subproces[subprocess_uuid].send_signal(signal)
- def subprocess_terminate(self, subprocess_uuid, timeout=60):
+ def subprocess_terminate(self, subprocess_uuid, timeout=60, check_return=True):
process = self.__subprocess[subprocess_uuid]
process.terminate()
- process.wait(timeout)
+ try:
+ process.wait(timeout)
+ except subprocess.TimeoutExpired:
+ # Force kill
+ return self.subprocess_kill(subprocess_uuid)
stdout, stderr = self.__stdout_stderr[subprocess_uuid]
stdout.close()
stderr.close()
+ if check_return:
+ if process.returncode != 0:
+ raise subprocess.CalledProcessError(process.returncode, process.args)
return process
def subprocess_kill(self, subprocess_uuid):
stderr.close()
return process
+ def subprocess_wait(self, subprocess_uuid, check_return=True):
+ process = self.__subprocess[subprocess_uuid]
+ process.wait()
+ stdout, stderr = self.__stdout_stderr[subprocess_uuid]
+ stdout.close()
+ stderr.close()
+ if check_return:
+ if process.returncode != 0:
+ raise subprocess.CalledProcessError(process.returncode, process.args)
+ return process
+
def get_subprocess_stdout_path(self, subprocess_uuid):
stdout, stderr = self.__stdout_stderr[subprocess_uuid]
return stdout.name
_logger.debug("Spawned sub pid: {} args: {} stdout: {} stderr{}".format(p.pid, p.args, out_path, err_path))
return tmp_id
- def run(self, command_line, cwd=None, check_return=True, ld_preload="", classpath=""):
+ def run(self, command_line, cwd=None, check_return=True, ld_preload="", classpath="", timeout=None):
"""
Run the command and return a tuple of a (CompletedProcess, stdout_path,
stderr_path). The subprocess is already executed and returned. The
for key, value in env.items():
env_out.write('{}={}\n'.format(key, value))
- cp = subprocess.run(args, stdout=stdout, stderr=stderr, env=env, cwd=cwd)
+ cp = subprocess.run(args, stdout=stdout, stderr=stderr, env=env,
+ cwd=cwd, timeout=timeout)
_logger.debug("Command #{} args: {} stdout: {} stderr{}".format(tmp_id, cp.args, out_path, err_path))
# Add to the global log file. This can help a little. Leave the other
def load_test_module(self):
# Base directory is provided by env
self.run("modprobe lttng-test")
+ self._is_test_modules_loaded = True
def unload_test_module(self, check_return=True):
# Base directory is provided by env
- self.run("modprobe -r lttng-test", check_return=check_return)
+ if self._is_test_modules_loaded:
+ self.run("modprobe -r lttng-test", check_return=check_return)
def close(self):
for key, subp in self.__subprocess.items():
- subp.terminate()
- for key, subp in self.__subprocess.items():
- # TODO move timeout to settings
- subp.wait(timeout=60)
- for key, (stdout, stderr) in self.__stdout_stderr.items():
- stdout.close()
- stderr.close()
+ self.subprocess_kill(key)
# Always try to remove test module but do not perform check on return
# value.
# Copy the lttng_home used at runtime using hardlink to prevent useless
# data duplication
shutil.copytree(self.lttng_home, self.__post_runtime_lttng_home_path, copy_function=os.link)
-