-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Switch to ThreadedChildWatcher and test #5877
Conversation
Codecov Report
@@ Coverage Diff @@
## master #5877 +/- ##
=======================================
Coverage 96.75% 96.75%
=======================================
Files 44 44
Lines 9851 9852 +1
Branches 1591 1591
=======================================
+ Hits 9531 9532 +1
Misses 182 182
Partials 138 138
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
Hey @sweatybridge, can you help me understand this change please? My understanding is that |
Hi @AustinScola, |
@sweatybridge, that makes sense. Thank you for the wonderful explanation! |
Happy to help! I'm looking forward to xdist support. |
Is this ready to be merged? |
@webknjaz could you take a look at this and merge it if possible? |
tests/test_loop.py
Outdated
def test_setup_loop_non_main_thread() -> None: | ||
def target() -> None: | ||
with loop_context(): | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we run something in this loop and maybe process some signal? This is what may go wrong potentially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting up the loop context in python 3.7 still uses SafeChildWatcher
, which in turn registers signals. I've updated the test to expect failure on python 3.7 and success in 3.8+. This way we have both code paths covered.
Subsequently after merging pytest-xdist
, we might see occasional failures on python 3.7 tests in CI for the same reason. This could happen with any tests that use the asyncio event loop, not specific to this test alone. This will be ok once we deprecate 3.7.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather vendor a backport and use it under Python 3.7. Also, it's not yet time to drop it anyway. aiohttp 3.8 still supports Python 3.6 even. It'll be EOL in 5 months but for CPython 3.7 there are 2 years to go.
Being a framework/library forces us to support a wider range of versions, unlike projects that are just apps bound to a single env.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, agree that backporting is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here's the backport with manually resolved merge conflicts #5919
try: | ||
with loop_context() as loop: | ||
assert asyncio.get_event_loop() is loop | ||
loop.run_until_complete(test_subprocess_co(loop)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this calls subprocesses but what about registering signal handlers? This is what actually fails on old watchers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Registering signal handlers will always fail in non-main thread, regardless of whether we are using old or new watcher. The new watcher avoids this issue by not registering signal handlers at all (using waitpid as alternative).
What we want to ensure in this test is that child processes can be watched, not whether signals can be successfully registered. In other words, since the library no longer registers signal handler on python 3.8, it's not relevant to cover signal registering in tests.
Am I misunderstanding something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The original problem with xdist was exactly the fact that there's a problem with the signal handlers that happens in an inconsistent manner. This is what blocks #5431 and all the previous attempts. I was sure that the new watchers were supposed to fix this based on what @asvetlov mentioned to me privately. Are you sure it's still problematic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I'm saying is signal handling is an independent problem from watching child process. The old watcher uses signal handling and will crash when mixed with xdist. The new watcher doesn't use signal handling and therefore is not problematic. Our test only need to verify that child process is watched, it doesn't matter whether it's implemented signals or not.
For reference, here's cpython's implementation for ThreadedChildWatcher
https://github.com/python/cpython/blob/3.8/Lib/asyncio/unix_events.py#L1296. It starts a new thread and calls waitpid
.
Compare that with SafeChildWatcher
which inherits from BaseChildWatcher
https://github.com/python/cpython/blob/3.8/Lib/asyncio/unix_events.py#L927. It tries to register signal handler and hence will raise an exception in non-main thread.
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll merge this "as is" for now. It's an improvement over what we had before. But it'd be really great to tackle that problem with the signals in order to make xdist enabled by default.
Backport to 3.8: 💔 cherry-picking failed — conflicts found❌ Failed to cleanly apply 33a38b8 on top of patchback/backports/3.8/33a38b8c358011fc8bc9198cd62a2a50b69bbc14/pr-5877 Backporting merged PR #5877 into master
🤖 @patchback |
@sweatybridge could you backport this manually? |
Co-authored-by: Sviatoslav Sydorenko <[email protected]> (cherry picked from commit 33a38b8)
* Switch to ThreadedChildWatcher and test (#5877) Co-authored-by: Sviatoslav Sydorenko <[email protected]> (cherry picked from commit 33a38b8) * Fix event loop access for py310 Co-authored-by: Andrew Svetlov <[email protected]>
What do these changes do?
Switch back to using
ThreadedChildWatcher
(originally introduced in #5862). Adds a unit test to ensure loop can be setup from non-main thread bypytest-xdist
.Are there changes in behavior for the user?
NA
Related issue number
#5852
Checklist
CONTRIBUTORS.txt
CHANGES
folder<issue_id>.<type>
for example (588.bugfix)issue_id
change it to the pr id after creating the pr.feature
: Signifying a new feature..bugfix
: Signifying a bug fix..doc
: Signifying a documentation improvement..removal
: Signifying a deprecation or removal of public API..misc
: A ticket has been closed, but it is not of interest to users.