diff --git a/pytools/__init__.py b/pytools/__init__.py index 978352257de801ad87898a49d7b9eda13a155e20..ded899c314670ddeb7c8b1721abaed405e4a21b6 100644 --- a/pytools/__init__.py +++ b/pytools/__init__.py @@ -2170,9 +2170,35 @@ class ProcessLogger(object): # pylint: disable=too-many-instance-attributes import threading self.late_start_log_thread = threading.Thread(target=self._log_start_if_long) + # Do not delay interpreter exit if thread not finished. self.late_start_log_thread.daemon = True - self.late_start_log_thread.start() + + # https://github.com/firedrakeproject/firedrake/issues/1422 + # Starting a thread may irrecoverably break various environments, + # e.g. MPI. + # + # Since the late-start logging is an optional 'quality-of-life' + # feature for interactive use, do not do it unless there is (weak) + # evidence of interactive use. + import sys + use_late_start_logging = sys.stdin.isatty() + + import os + if os.environ.get("PYTOOLS_LOG_NO_THREADS", ""): + use_late_start_logging = False + + if use_late_start_logging: + try: + self.late_start_log_thread.start() + except RuntimeError: + # https://github.com/firedrakeproject/firedrake/issues/1422 + # + # Starting a thread may fail in various environments, e.g. MPI. + # Since the late-start logging is an optional 'quality-of-life' + # feature for interactive use, tolerate failures of it without + # warning. + pass self.timer = ProcessTimer() diff --git a/test/test_pytools.py b/test/test_pytools.py index 91748c82e52fc2b362023adc096116417d9db2d1..775b68b1e94f69135f19393664e5353852222a49 100644 --- a/test/test_pytools.py +++ b/test/test_pytools.py @@ -1,9 +1,11 @@ from __future__ import absolute_import, division, with_statement import sys - import pytest +import logging +logger = logging.getLogger(__name__) + @pytest.mark.skipif("sys.version_info < (2, 5)") def test_memoize_method_clear(): @@ -185,6 +187,18 @@ def test_reshaped_view(): pytools.reshaped_view(b, -1) +def test_processlogger(): + logging.basicConfig(level=logging.INFO) + + from pytools import ProcessLogger + plog = ProcessLogger(logger, "testing the process logger", + long_threshold_seconds=0.01) + + from time import sleep + with plog: + sleep(0.3) + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1])