GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-81554: Add add_reader support to ProactorEventLoop by minrk · Pull Request #141834 · python/cpython Conversation
|
| # SPDX-License-Identifier: PSF-2.0 AND Apache-2.0 | ||
| # SPDX-FileCopyrightText: Copyright (c) 2025 The Tornado Authors |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Should this not be in https://github.com/python/cpython/blob/main/Misc/sbom.spdx.json?
See the devguide.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This is not perfectly as-is, since it is adapted and an excerpt, like Lib/asyncio/events.py and a number of others. That doesn't seem to fit the SBOM requirements, in my understanding? I don't see any of the other similarly adapted files in sbom.spdx.json.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
After addressing review, it has diverged more substantially. This comment structure seems to be how adapted/partial content is handled. Is there anything in the dev guide for that? I couldn't find it. The SBOM page doesn't seem to apply or mention this sort of case.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Co-authored-by: Stan Ulbrych <[email protected]>
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| # introduction of a new hook: https://bugs.python.org/issue41962) | ||
| self._thread = threading.Thread( | ||
| name="Tornado selector", | ||
| daemon=True, |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to avoid daemon thread?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
#86128 discusses why this is a daemon thread. I believe we need to call
with loop._select_cond: loop._closing_selector = True loop._select_cond.notify() try: loop._waker_w.send(b"a") except BlockingIOError: pass
prior to thread.join() for it to wake and exit properly. It looks like I can make it a non-daemon thread if I register the atexit hook with the private threading._register_atexit.
I believe this is only needed to handle process teardown for unclosed event loops. If we can strictly guarantee that EventLoop.close() is called before non-daemon threads are joined, then I don't think this is an issue. But I don't personally know a reliable way other than threading._register_atexit.
atexit.register only runs after threads are joined, not non-daemon threads (hence #86128), meaning that switching the thread to non-daemon will hang process exit until select returns, because no wake is called. A public hook that does exactly what threading._register_atexit does would be great. But since this is now in the stdlib, I could use that here, I suppose (#86128 remains a problem for non-stdlib code, of course).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
matches tornado behavior tornado handles this in IOLoop, so we need to include it
- remove some older Python compatibility, since this is in the stdlib now - resolve race between selector thread call soon and EventLoop.close
rely on private threading._register_atexit to run cleanup prior to thread join
based on confusion in feedback
according to devguide
| When called, :func:`select.select` is run in an additional thread. | ||
|
|
||
| The resolution of the monotonic clock on Windows is usually around 15.6 | ||
| milliseconds. The best resolution is 0.5 milliseconds. The resolution depends on the |
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
"The resolution of the monotonic clock on Windows is usually around 15.6 milliseconds."
Note unrelated to this PR: that's no longer true in Python 3.13:
On Windows, monotonic() now uses the QueryPerformanceCounter() clock for a resolution of 1 microsecond, instead of the GetTickCount64() clock which has a resolution of 15.6 milliseconds.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Co-authored-by: Victor Stinner <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Overall, the change looks good to me. I didn't test it. I just trust tests and the code that I read :-) I would prefer to have a second review from another core dev.
@kumaraditya303: Would you be interested to review this change?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| with mock.patch("select.select", wraps=select.select) as mock_select: | ||
| self.selector_thread.add_reader(b, mock_recv) | ||
| # ready event, but main event loop is blocked for some time | ||
| time.sleep(0.1) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Is this sleep really needed? If yes, can it be replaced with a synchronization primitive instead of a sleep?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I would love help writing tests to verify that things don't happen in multithreaded code.
This was added to demonstrate an answer to the question in review that the select loop doesn't keep firing away if the main loop is slow to process one event, and was the best I could come up with to demonstrate that it really is waiting and only calls select once.
The sequence of events that we want to wait for is that the select thread is waiting in select_cond.wait() after select is called the first time. Maybe there's a way to instrument that.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This PR is stale because it has been open for 30 days with no activity. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
will it be a problem if it's not in python-3.15 final ? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Documentation build overview
3 files changed± library/asyncio-eventloop.html± library/asyncio-platforms.html± whatsnew/changelog.html |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
|
|
||
| def tearDownModule(): | ||
| asyncio.events._set_event_loop_policy(None) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It seems like asyncio.events._set_event_loop_policy() has been removed.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
thanks, updated and fixed lint
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Yes, it will continue to be a problem, but not a particularly new one (at least since 3.8 made proactor default). Though the typical workaround of using |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.