summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2019-12-23 15:44:36 -0500
committerNed Batchelder <ned@nedbatchelder.com>2019-12-23 18:01:49 -0500
commit7fb6fc15d88778f15a49ab1e63bdf550c2c7c981 (patch)
treea4985bf25d77981e8894e15a8bbe4f2f49fdde79
parent42a651c6e23b4156c5bc37208d97d0788e09edf7 (diff)
downloadpython-coveragepy-git-7fb6fc15d88778f15a49ab1e63bdf550c2c7c981.tar.gz
Catch and display expceptions during multiprocessing bootstrap.
-rw-r--r--coverage/multiproc.py18
-rw-r--r--tests/test_concurrency.py17
2 files changed, 30 insertions, 5 deletions
diff --git a/coverage/multiproc.py b/coverage/multiproc.py
index bab81475..c466301f 100644
--- a/coverage/multiproc.py
+++ b/coverage/multiproc.py
@@ -6,6 +6,8 @@
import multiprocessing
import multiprocessing.process
import os
+import sys
+import traceback
from coverage import env
from coverage.misc import contract
@@ -27,14 +29,20 @@ class ProcessWithCoverage(OriginalProcess): # pylint: disable=abstract-m
def _bootstrap(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Wrapper around _bootstrap to start coverage."""
- from coverage import Coverage # avoid circular import
- cov = Coverage(data_suffix=True)
- cov._warn_preimported_source = False
- cov.start()
- debug = cov._debug
try:
+ from coverage import Coverage # avoid circular import
+ cov = Coverage(data_suffix=True)
+ cov._warn_preimported_source = False
+ cov.start()
+ debug = cov._debug
if debug.should("multiproc"):
debug.write("Calling multiprocessing bootstrap")
+ except Exception:
+ print("Exception during multiprocessing bootstrap init:")
+ traceback.print_exc(file=sys.stdout)
+ sys.stdout.flush()
+ raise
+ try:
return original_bootstrap(self, *args, **kwargs)
finally:
if debug.should("multiproc"):
diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py
index 436df803..3a127499 100644
--- a/tests/test_concurrency.py
+++ b/tests/test_concurrency.py
@@ -476,6 +476,23 @@ class MultiprocessingTest(CoverageTest):
expected_out = "{nprocs} pids, total = {total}".format(nprocs=nprocs, total=total)
self.try_multiprocessing_code_with_branching(code, expected_out)
+ def test_multiprocessing_bootstrap_error_handling(self):
+ # An exception during bootstrapping will be reported.
+ self.make_file("multi.py", """\
+ import multiprocessing
+ if __name__ == "__main__":
+ with multiprocessing.Manager():
+ pass
+ """)
+ self.make_file(".coveragerc", """\
+ [run]
+ concurrency = multiprocessing
+ _crash = _bootstrap
+ """)
+ out = self.run_command("coverage run multi.py")
+ self.assertIn("Exception during multiprocessing bootstrap init", out)
+ self.assertIn("Exception: Crashing because called by _bootstrap", out)
+
def test_coverage_stop_in_threads():
has_started_coverage = []