-
-
Notifications
You must be signed in to change notification settings - Fork 438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coverage measurement fails on code containing os.exec* methods #43
Comments
Original comment by Geoff Bache (Bitbucket: geoffbache, GitHub: Unknown) Sorry, didn't mean to report this anonymously. |
Original comment by Geoff Bache (Bitbucket: geoffbache, GitHub: Unknown) I have a patch for this one also if you're interested. |
I'd be interested to see a patch. It sounds very involved! |
Original comment by Geoff Bache (Bitbucket: geoffbache, GitHub: Unknown) Patch attached against current trunk. Could be simplified if it assumed that these functions called each other internally, which they do currently. Tested with a small program as follows
which I can now get coverage information out of. |
I haven't applied the patch yet, because I'd only heard one request for it (this ticket), and I am averse to monkeypatching. But I now have a second request, and this is a fairly small patch. Interestingly, if execvpe would execute the atexit-registered handlers before changing the process over, it would just work. I created http://bugs.python.org/issue16822 to request Python to be fixed. |
Considering this for the next release. |
For anyone looking for Geoff's changes:
and then:
|
Original comment by Geoff Bache (Bitbucket: geoffbache, GitHub: Unknown) Looking at this again. There are other circumstances where no coverage information is produced because the atexit handlers are not called:
In the light of this, I'm wondering if a generic, if slightly clumsy, solution would be simply to provide a "process_shutdown" method (in a similar way to process_startup) so that this external handler could be called explicitly in any of these circumstances. Then it's easy to add code like
and call it in signal handlers, just before os.exec* or in a JVM exit handler to work around all these cases. Would be better of course if it was detected automatically, but this will avoid the evils of monkey patching and is more generic than the code I posted here. Can provide a patch if you agree to the solution. |
Original comment by Geoff Bache (Bitbucket: geoffbache, GitHub: Unknown) Implementing a solution like this now appears to be difficult, as the "coverage" object is not necessarily stored in a global variable any more. I resorted to the following in my code, which does not require patching coverage at all, but only works under Python 2 and relies on an undocumented feature of Python's atexit module:
Clearly not ideal but about the only thing I could think of to get my coverage measurement working with the latest version. |
CC.
|
* execute "python-coverage report" with python3 * coverage.process_startup() returns None if coverage was already started. This is the case on os.fork(). * update broken bitbucket links: nedbat/coveragepy#310 nedbat/coveragepy#43
Here's another hack that seems to work for Python 3, at least with
|
What's the 2023 solution to this issue with latest |
Nothing new has happened. Can you tell us more about how and why os.exec is involved? It's a difficult thing to put a leash around with certainty. |
I have a function that calls My testing code looks as follows (to prevent pytest crashing when the process is replaced). Minimal reproduction: from multiprocessing import Process
import os
def func_execv(cmd, args):
os.execvp(cmd, args)
def test_func_execv(capfd):
cmd = "echo"
args = [cmd, "test"]
p = Process(target=func_execv, args=(cmd, args))
p.start()
p.join()
assert "test" in capfd.readouterr().out Run this file with I have to execute the The code in
|
Do the steps for subprocess measurement help? https://coverage.readthedocs.io/en/7.3.2/subprocess.html |
I've added the suggested line to Can you suggest a basic setup with the minimum reproduction example where it would work? |
Originally reported by Anonymous
I recently tried to measure coverage of a program that calls os.execvpe, essentially causing the process to be replaced by a different one. This did not record any coverage information at all.
The reason of course is that os.execvpe does not return, so there is no opportunity to call coverage.stop() and coverage.save() as is done if e.g. an exception is thrown. I'd suggest this method could be "monkey-patched" so that such code can be inserted before it.
(and also the other 7 os.exec* methods of course)
The text was updated successfully, but these errors were encountered: