-
Notifications
You must be signed in to change notification settings - Fork 3.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
asyncio: stop using get_event_loop(). introduce ~singleton loop. #7792
Conversation
asyncio.get_event_loop() became deprecated in python3.10. (see python/cpython#83710) ``` .../electrum/electrum/daemon.py:470: DeprecationWarning: There is no current event loop self.asyncio_loop = asyncio.get_event_loop() .../electrum/electrum/network.py:276: DeprecationWarning: There is no current event loop self.asyncio_loop = asyncio.get_event_loop() ``` Also, according to that thread, "set_event_loop() [... is] not deprecated by oversight". So, we stop using get_event_loop() and set_event_loop() in our own code. Note that libraries we use (such as the stdlib for python <3.10), might call get_event_loop, which then relies on us having called set_event_loop e.g. for the GUI thread. To work around this, a custom event loop policy providing a get_event_loop implementation is used. Previously, we have been using a single asyncio event loop, created with util.create_and_start_event_loop, and code in many places got a reference to this loop using asyncio.get_event_loop(). Now, we still use a single asyncio event loop, but it is now stored as a global in util._asyncio_event_loop (access with util.get_asyncio_loop()). I believe these changes also fix spesmilo#5376
b6a14a2
to
8ba58b8
Compare
great work |
self.electrum_path = tempfile.mkdtemp() | ||
|
||
def tearDown(self): | ||
self.asyncio_loop.call_soon_threadsafe(self._stop_loop.set_result, 1) |
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.
why is super().tearDown()
not called first?
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.
Although in many cases the order does not matter, here it might, depending on the unit test framework running the tests I guess: SequentialTestCase.setUp()
and SequentialTestCase.tearDown()
take and release self.test_lock
, which ensure that tests do not run in parallel. If super().tearDown()
is called before we stop the asyncio loop, and the test framework supports running tests in parallel, some tests might fail when trying to create an "overlapping" event loop.
The natural order of calling destructors is the reverse of constructors: Create parent first, child next, but destroy child first, parent next (btw this is the order in C++, where the calls happen implicitly). Code in the child might be relying on code in the parent, so the parent shouldn't be destroyed first. I guess we could clean up the rest of the tearDown
implementations to respect this.
8ba58b8
to
872ce82
Compare
removed. |
asyncio.get_event_loop()
became deprecated in python3.10. (see python/cpython#83710)Also, according to that thread, "set_event_loop() [... is] not deprecated by oversight".
So, we stop using
get_event_loop()
andset_event_loop()
in our own code.Note that libraries we use (such as the stdlib for python <3.10), might call
get_event_loop
,which then relies on us having called
set_event_loop
e.g. for the GUI thread. To work aroundthis, a custom event loop policy providing a
get_event_loop
implementation is used.Previously, we have been using a single asyncio event loop, created with
util.create_and_start_event_loop
, and code in many places got a reference to this loopusing
asyncio.get_event_loop()
.Now, we still use a single asyncio event loop, but it is now stored as a global in
util._asyncio_event_loop
(access withutil.get_asyncio_loop()
).I believe these changes also fix #5376