diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2016-01-10 12:37:36 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2016-01-10 12:37:36 -0500 |
commit | 7865e5067d30c98f280ad06175b26c93508783c5 (patch) | |
tree | feb82c87c38795f13f2da6746848d2b9ebb882e7 /coverage/monkey.py | |
parent | f6d343cf2259491ce9556758c5398e0db76d804c (diff) | |
download | python-coveragepy-git-7865e5067d30c98f280ad06175b26c93508783c5.tar.gz |
Make multiprocessing support work with spawned processes, which is what Windows uses.
Diffstat (limited to 'coverage/monkey.py')
-rw-r--r-- | coverage/monkey.py | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/coverage/monkey.py b/coverage/monkey.py index b896dbf5..3f78d7dc 100644 --- a/coverage/monkey.py +++ b/coverage/monkey.py @@ -12,7 +12,6 @@ import sys PATCHED_MARKER = "_coverage$patched" if sys.version_info >= (3, 4): - klass = multiprocessing.process.BaseProcess else: klass = multiprocessing.Process @@ -49,4 +48,33 @@ def patch_multiprocessing(): else: multiprocessing.Process = ProcessWithCoverage + # 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 + # objects into the data that gets pickled and sent to the sub-process. When + # the Stowaway is unpickled, it's __setstate__ method is called, which + # re-applies the monkey-patch. + # Windows only spawns, so this is needed to keep Windows working. + try: + from multiprocessing import spawn + original_get_preparation_data = spawn.get_preparation_data + except (ImportError, AttributeError): + pass + else: + def get_preparation_data_with_stowaway(name): + """Get the original preparation data, and also insert our stowaway.""" + d = original_get_preparation_data(name) + d['stowaway'] = Stowaway() + return d + + spawn.get_preparation_data = get_preparation_data_with_stowaway + setattr(multiprocessing, PATCHED_MARKER, True) + + +class Stowaway(object): + """An object to pickle, so when it is unpickled, it can apply the monkey-patch.""" + def __getstate__(self): + return {} + + def __setstate__(self, state): + patch_multiprocessing() |