diff --git a/libcxx/utils/libcxx/util.py b/libcxx/utils/libcxx/util.py --- a/libcxx/utils/libcxx/util.py +++ b/libcxx/utils/libcxx/util.py @@ -253,24 +253,27 @@ TODO: Reimplement this without using psutil so we can remove our dependency on it. """ - import psutil - try: - psutilProc = psutil.Process(pid) - # Handle the different psutil API versions + if platform.system() == 'AIX': + subprocess.call('kill -kill $(ps -o pid= -L{})'.format(pid), shell=True) + else: + import psutil try: - # psutil >= 2.x - children_iterator = psutilProc.children(recursive=True) - except AttributeError: - # psutil 1.x - children_iterator = psutilProc.get_children(recursive=True) - for child in children_iterator: + psutilProc = psutil.Process(pid) + # Handle the different psutil API versions try: - child.kill() - except psutil.NoSuchProcess: - pass - psutilProc.kill() - except psutil.NoSuchProcess: - pass + # psutil >= 2.x + children_iterator = psutilProc.children(recursive=True) + except AttributeError: + # psutil 1.x + children_iterator = psutilProc.get_children(recursive=True) + for child in children_iterator: + try: + child.kill() + except psutil.NoSuchProcess: + pass + psutilProc.kill() + except psutil.NoSuchProcess: + pass def executeCommandVerbose(cmd, *args, **kwargs): diff --git a/lldb/lit/lit.cfg.py b/lldb/lit/lit.cfg.py --- a/lldb/lit/lit.cfg.py +++ b/lldb/lit/lit.cfg.py @@ -1,6 +1,7 @@ # -*- Python -*- import os +import platform import re import shutil import site @@ -75,13 +76,14 @@ shutil.rmtree(cachedir) # Set a default per-test timeout of 10 minutes. Setting a timeout per test -# requires the psutil module and lit complains if the value is set but the -# module can't be found. -try: - import psutil # noqa: F401 +# requires that killProcessAndChildren() is supported on the platform and +# lit complains if the value is set but it is not supported. +supported, errormsg = lit_config.maxIndividualTestTimeIsSupported +if supported: lit_config.maxIndividualTestTime = 600 -except ImportError: - pass +else: + lit_config.warning("Could not set a default per-test timeout. " + errormsg) + # If running tests natively, check for CPU features needed for some tests. diff --git a/llvm/utils/lit/lit/LitConfig.py b/llvm/utils/lit/lit/LitConfig.py --- a/llvm/utils/lit/lit/LitConfig.py +++ b/llvm/utils/lit/lit/LitConfig.py @@ -1,6 +1,7 @@ from __future__ import absolute_import import inspect import os +import platform import sys import lit.Test @@ -76,6 +77,19 @@ """ return self._maxIndividualTestTime + @property + def maxIndividualTestTimeIsSupported(self): + """ + Returns a tuple ( , ) + where + `` is True if setting maxIndividualTestTime is supported + on the current host, returns False otherwise. + `` is an empty string if `` is True, + otherwise is contains a string describing why setting + maxIndividualTestTime is not supported. + """ + return lit.util.killProcessAndChildrenIsSupported() + @maxIndividualTestTime.setter def maxIndividualTestTime(self, value): """ @@ -86,16 +100,13 @@ self.fatal('maxIndividualTestTime must set to a value of type int.') self._maxIndividualTestTime = value if self.maxIndividualTestTime > 0: - # The current implementation needs psutil to set + # The current implementation needs psutil on some platforms to set # a timeout per test. Check it's available. # See lit.util.killProcessAndChildren() - try: - import psutil # noqa: F401 - except ImportError: - self.fatal("Setting a timeout per test requires the" - " Python psutil module but it could not be" - " found. Try installing it via pip or via" - " your operating system's package manager.") + supported, errormsg = self.maxIndividualTestTimeIsSupported + if not supported: + self.fatal('Setting a timeout per test not supported. ' + + errormsg) elif self.maxIndividualTestTime < 0: self.fatal('The timeout per test must be >= 0 seconds') diff --git a/llvm/utils/lit/lit/util.py b/llvm/utils/lit/lit/util.py --- a/llvm/utils/lit/lit/util.py +++ b/llvm/utils/lit/lit/util.py @@ -423,34 +423,56 @@ return out.decode() return None +def killProcessAndChildrenIsSupported(): + """ + Returns a tuple ( , ) + where + `` is True if `killProcessAndChildren()` is supported on + the current host, returns False otherwise. + `` is an empty string if `` is True, + otherwise is contains a string describing why the function is + not supported. + """ + if platform.system() == 'AIX': + return (True, "") + try: + import psutil # noqa: F401 + return (True, "") + except ImportError: + return (False, "Requires the Python psutil module but it could" + " not be found. Try installing it via pip or via" + " your operating system's package manager.") def killProcessAndChildren(pid): """This function kills a process with ``pid`` and all its running children - (recursively). It is currently implemented using the psutil module which - provides a simple platform neutral implementation. + (recursively). It is currently implemented using the psutil module on some + plaftorms which provides a simple platform neutral implementation. - TODO: Reimplement this without using psutil so we can remove - our dependency on it. + TODO: Reimplement this without using psutil on all platforms so we can + remove our dependency on it. """ - import psutil - try: - psutilProc = psutil.Process(pid) - # Handle the different psutil API versions + if platform.system() == 'AIX': + subprocess.call('kill -kill $(ps -o pid= -L{})'.format(pid), shell=True) + else: + import psutil try: - # psutil >= 2.x - children_iterator = psutilProc.children(recursive=True) - except AttributeError: - # psutil 1.x - children_iterator = psutilProc.get_children(recursive=True) - for child in children_iterator: + psutilProc = psutil.Process(pid) + # Handle the different psutil API versions try: - child.kill() - except psutil.NoSuchProcess: - pass - psutilProc.kill() - except psutil.NoSuchProcess: - pass + # psutil >= 2.x + children_iterator = psutilProc.children(recursive=True) + except AttributeError: + # psutil 1.x + children_iterator = psutilProc.get_children(recursive=True) + for child in children_iterator: + try: + child.kill() + except psutil.NoSuchProcess: + pass + psutilProc.kill() + except psutil.NoSuchProcess: + pass try: diff --git a/llvm/utils/lit/tests/googletest-timeout.py b/llvm/utils/lit/tests/googletest-timeout.py --- a/llvm/utils/lit/tests/googletest-timeout.py +++ b/llvm/utils/lit/tests/googletest-timeout.py @@ -1,4 +1,4 @@ -# REQUIRES: python-psutil +# REQUIRES: lit-max-individual-test-time # Check that the per test timeout is enforced when running GTest tests. # diff --git a/llvm/utils/lit/tests/lit.cfg b/llvm/utils/lit/tests/lit.cfg --- a/llvm/utils/lit/tests/lit.cfg +++ b/llvm/utils/lit/tests/lit.cfg @@ -1,6 +1,7 @@ # -*- Python -*- import os +import platform import sys import lit.formats @@ -56,10 +57,10 @@ os.path.dirname(__file__), ".coveragerc") # Add a feature to detect if psutil is available -try: - import psutil - lit_config.note('Found python psutil module') - config.available_features.add("python-psutil") -except ImportError: - lit_config.warning('Could not import psutil. Some tests will be skipped and' - ' the --timeout command line argument will not work.') +supported, errormsg = lit_config.maxIndividualTestTimeIsSupported +if supported: + config.available_features.add("lit-max-individual-test-time") +else: + lit_config.warning('Setting a timeout per test not supported. ' + errormsg + + ' Some tests will be skipped and the --timeout' + ' command line argument will not work.') diff --git a/llvm/utils/lit/tests/shtest-timeout.py b/llvm/utils/lit/tests/shtest-timeout.py --- a/llvm/utils/lit/tests/shtest-timeout.py +++ b/llvm/utils/lit/tests/shtest-timeout.py @@ -1,4 +1,4 @@ -# REQUIRES: python-psutil +# REQUIRES: lit-max-individual-test-time # llvm.org/PR33944 # UNSUPPORTED: system-windows