summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2021-08-19 12:46:42 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-08-23 08:30:54 +0100
commit4df610473f21da79164ed01927103d13240d4c2a (patch)
tree9f125b4888017e5c9be825c53a855fd54e4e3888 /bitbake
parentfdc908f321da852856a07c19e3d9a33ccb273dda (diff)
downloadpoky-4df610473f21da79164ed01927103d13240d4c2a.tar.gz
bitbake: bitbake: asyncrpc: always create new asyncio loops
asyncio in older Python 3.x (seen with 3.7) can seemingly hang if new_event_loop is called repeatedly in the same process. The reuse of processes in the Bitbake thread pool during parsing seems to be able to trigger this with the PR server export selftest. It appears that calling set_event_loop with the new loop avoids the issue, so that is now done in the asyncrpc Client initializer (with an explanatory comment). This should be revisited when the day arrives that Python 3.9 becomes the minimum required for BitBake. Additionally, it was discovered that using get_event_loop in the asyncrpc server initialization can trigger hangs in the hashserv unittests when the second test is run. To avoid this, switch to calling new_event_loop + set_event_loop in the initialization code there as well. (Bitbake rev: bb9a36563505652294b20b4c88199b24fa208342) Signed-off-by: Scott Murray <scott.murray@konsulko.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/bb/asyncrpc/client.py10
-rw-r--r--bitbake/lib/bb/asyncrpc/serv.py24
2 files changed, 30 insertions, 4 deletions
diff --git a/bitbake/lib/bb/asyncrpc/client.py b/bitbake/lib/bb/asyncrpc/client.py
index 3eb4fdde8a..50e60d5c31 100644
--- a/bitbake/lib/bb/asyncrpc/client.py
+++ b/bitbake/lib/bb/asyncrpc/client.py
@@ -119,6 +119,16 @@ class Client(object):
119 self.client = self._get_async_client() 119 self.client = self._get_async_client()
120 self.loop = asyncio.new_event_loop() 120 self.loop = asyncio.new_event_loop()
121 121
122 # Override any pre-existing loop.
123 # Without this, the PR server export selftest triggers a hang
124 # when running with Python 3.7. The drawback is that there is
125 # potential for issues if the PR and hash equiv (or some new)
126 # clients need to both be instantiated in the same process.
127 # This should be revisited if/when Python 3.9 becomes the
128 # minimum required version for BitBake, as it seems not
129 # required (but harmless) with it.
130 asyncio.set_event_loop(self.loop)
131
122 self._add_methods('connect_tcp', 'close', 'ping') 132 self._add_methods('connect_tcp', 'close', 'ping')
123 133
124 @abc.abstractmethod 134 @abc.abstractmethod
diff --git a/bitbake/lib/bb/asyncrpc/serv.py b/bitbake/lib/bb/asyncrpc/serv.py
index 45628698b6..b4cffff213 100644
--- a/bitbake/lib/bb/asyncrpc/serv.py
+++ b/bitbake/lib/bb/asyncrpc/serv.py
@@ -136,10 +136,7 @@ class AsyncServer(object):
136 self.logger = logger 136 self.logger = logger
137 self.start = None 137 self.start = None
138 self.address = None 138 self.address = None
139 139 self.loop = None
140 @property
141 def loop(self):
142 return asyncio.get_event_loop()
143 140
144 def start_tcp_server(self, host, port): 141 def start_tcp_server(self, host, port):
145 def start_tcp(): 142 def start_tcp():
@@ -228,6 +225,12 @@ class AsyncServer(object):
228 """ 225 """
229 Serve requests in the current process 226 Serve requests in the current process
230 """ 227 """
228 # Create loop and override any loop that may have existed in
229 # a parent process. It is possible that the usecases of
230 # serve_forever might be constrained enough to allow using
231 # get_event_loop here, but better safe than sorry for now.
232 self.loop = asyncio.new_event_loop()
233 asyncio.set_event_loop(self.loop)
231 self.start() 234 self.start()
232 self._serve_forever() 235 self._serve_forever()
233 236
@@ -236,6 +239,19 @@ class AsyncServer(object):
236 Serve requests in a child process 239 Serve requests in a child process
237 """ 240 """
238 def run(queue): 241 def run(queue):
242 # Create loop and override any loop that may have existed
243 # in a parent process. Without doing this and instead
244 # using get_event_loop, at the very minimum the hashserv
245 # unit tests will hang when running the second test.
246 # This happens since get_event_loop in the spawned server
247 # process for the second testcase ends up with the loop
248 # from the hashserv client created in the unit test process
249 # when running the first testcase. The problem is somewhat
250 # more general, though, as any potential use of asyncio in
251 # Cooker could create a loop that needs to replaced in this
252 # new process.
253 self.loop = asyncio.new_event_loop()
254 asyncio.set_event_loop(self.loop)
239 try: 255 try:
240 self.start() 256 self.start()
241 finally: 257 finally: