Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] global_event_loop: return running loop for current thread
Date: Mon, 04 Jan 2021 09:06:54
Message-Id: 20210104090631.1584444-1-zmedico@gentoo.org
1 Like asyncio.get_event_loop(), return the running loop for the
2 current thread if there is one, and otherwise construct a new
3 one if needed. This allows the _safe_loop function to become
4 synonymous with the global_event_loop function.
5
6 Bug: https://bugs.gentoo.org/763339
7 Signed-off-by: Zac Medico <zmedico@g.o>
8 ---
9 .../util/_eventloop/global_event_loop.py | 28 ++-----------------
10 lib/portage/util/futures/_asyncio/__init__.py | 22 ++++++++++-----
11 2 files changed, 17 insertions(+), 33 deletions(-)
12
13 diff --git a/lib/portage/util/_eventloop/global_event_loop.py b/lib/portage/util/_eventloop/global_event_loop.py
14 index 413011178..bf314dc34 100644
15 --- a/lib/portage/util/_eventloop/global_event_loop.py
16 +++ b/lib/portage/util/_eventloop/global_event_loop.py
17 @@ -1,28 +1,4 @@
18 -# Copyright 2012-2020 Gentoo Authors
19 +# Copyright 2012-2021 Gentoo Authors
20 # Distributed under the terms of the GNU General Public License v2
21
22 -import portage
23 -from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop
24 -
25 -_instances = {}
26 -
27 -
28 -def global_event_loop():
29 - """
30 - Get a global EventLoop (or compatible object) instance which
31 - belongs exclusively to the current process.
32 - """
33 -
34 - pid = portage.getpid()
35 - instance = _instances.get(pid)
36 - if instance is not None:
37 - return instance
38 -
39 - constructor = AsyncioEventLoop
40 -
41 - # Use the _asyncio_wrapper attribute, so that unit tests can compare
42 - # the reference to one retured from _wrap_loop(), since they should
43 - # not close the loop if it refers to a global event loop.
44 - instance = constructor()._asyncio_wrapper
45 - _instances[pid] = instance
46 - return instance
47 +from portage.util.futures._asyncio import _safe_loop as global_event_loop
48 diff --git a/lib/portage/util/futures/_asyncio/__init__.py b/lib/portage/util/futures/_asyncio/__init__.py
49 index d39f31786..ab1468d43 100644
50 --- a/lib/portage/util/futures/_asyncio/__init__.py
51 +++ b/lib/portage/util/futures/_asyncio/__init__.py
52 @@ -1,4 +1,4 @@
53 -# Copyright 2018-2020 Gentoo Authors
54 +# Copyright 2018-2021 Gentoo Authors
55 # Distributed under the terms of the GNU General Public License v2
56
57 __all__ = (
58 @@ -37,9 +37,6 @@ portage.proxy.lazyimport.lazyimport(globals(),
59 'portage.util.futures:compat_coroutine@_compat_coroutine',
60 )
61 from portage.util._eventloop.asyncio_event_loop import AsyncioEventLoop as _AsyncioEventLoop
62 -from portage.util._eventloop.global_event_loop import (
63 - global_event_loop as _global_event_loop,
64 -)
65 # pylint: disable=redefined-builtin
66 from portage.util.futures.futures import (
67 CancelledError,
68 @@ -238,7 +235,7 @@ def _wrap_loop(loop=None):
69 # The default loop returned by _wrap_loop should be consistent
70 # with global_event_loop, in order to avoid accidental registration
71 # of callbacks with a loop that is not intended to run.
72 - loop = loop or _global_event_loop()
73 + loop = loop or _safe_loop()
74 return (loop if hasattr(loop, '_asyncio_wrapper')
75 else _AsyncioEventLoop(loop=loop))
76
77 @@ -267,8 +264,9 @@ def _safe_loop():
78 @rtype: asyncio.AbstractEventLoop (or compatible)
79 @return: event loop instance
80 """
81 - if portage._internal_caller or threading.current_thread() is threading.main_thread():
82 - return _global_event_loop()
83 + loop = _get_running_loop()
84 + if loop is not None:
85 + return loop
86
87 thread_key = threading.get_ident()
88 with _thread_weakrefs.lock:
89 @@ -286,6 +284,16 @@ def _safe_loop():
90 return loop
91
92
93 +def _get_running_loop():
94 + with _thread_weakrefs.lock:
95 + if _thread_weakrefs.pid == portage.getpid():
96 + try:
97 + loop = _thread_weakrefs.loops[threading.get_ident()]
98 + except KeyError:
99 + return None
100 + return loop if loop.is_running() else None
101 +
102 +
103 def _thread_weakrefs_atexit():
104 with _thread_weakrefs.lock:
105 if _thread_weakrefs.pid == portage.getpid():
106 --
107 2.26.2

Replies