diff --git a/CHANGES.rst b/CHANGES.rst index 9ba439f99..4a177a19f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -21,10 +21,16 @@ want to know what's different in 5.0 since 4.5.x, see :ref:`whatsnew5x`. .. Version 7.8.1 --- 2021-07-27 .. ---------------------------- + Unreleased ---------- -Nothing yet. +- Programs that used multiprocessing and changed directories would fail under + coverage. This is now fixed (`issue 890`_). A side effect is that debug + information about the config files read now shows absolute paths to the + files. + +.. _issue 890: https://github.com/nedbat/coveragepy/issues/890 .. _changes_501: diff --git a/coverage/config.py b/coverage/config.py index 452d320e3..78a3e86a1 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -6,6 +6,7 @@ import collections import copy import os +import os.path import re from coverage import env @@ -275,7 +276,7 @@ def from_file(self, filename, our_file): if not files_read: return False - self.config_files_read.extend(files_read) + self.config_files_read.extend(map(os.path.abspath, files_read)) any_set = False try: @@ -323,7 +324,7 @@ def from_file(self, filename, our_file): used = any_set if used: - self.config_file = filename + self.config_file = os.path.abspath(filename) with open(filename) as f: self._config_contents = f.read() diff --git a/coverage/multiproc.py b/coverage/multiproc.py index c466301f5..2931b3be0 100644 --- a/coverage/multiproc.py +++ b/coverage/multiproc.py @@ -6,6 +6,7 @@ import multiprocessing import multiprocessing.process import os +import os.path import sys import traceback @@ -85,7 +86,7 @@ def patch_multiprocessing(rcfile): # Set the value in ProcessWithCoverage that will be pickled into the child # process. - os.environ["COVERAGE_RCFILE"] = rcfile + os.environ["COVERAGE_RCFILE"] = os.path.abspath(rcfile) # When spawning processes rather than forking them, we have no state in the # new process. We sneak in there with a Stowaway: we stuff one of our own diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py index 3a1274999..9bfd88caf 100644 --- a/tests/test_concurrency.py +++ b/tests/test_concurrency.py @@ -493,6 +493,25 @@ def test_multiprocessing_bootstrap_error_handling(self): self.assertIn("Exception during multiprocessing bootstrap init", out) self.assertIn("Exception: Crashing because called by _bootstrap", out) + def test_bug890(self): + # chdir in multiprocessing shouldn't keep us from finding the + # .coveragerc file. + self.make_file("multi.py", """\ + import multiprocessing, os, os.path + if __name__ == "__main__": + if not os.path.exists("./tmp"): os.mkdir("./tmp") + os.chdir("./tmp") + with multiprocessing.Manager(): + pass + print("ok") + """) + self.make_file(".coveragerc", """\ + [run] + concurrency = multiprocessing + """) + out = self.run_command("coverage run multi.py") + self.assertEqual(out.splitlines()[-1], "ok") + def test_coverage_stop_in_threads(): has_started_coverage = []