Skip to content

Commit 4b4fc27

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "tests: Use GreenThreadPoolExecutor.shutdown(wait=True)" into stable/2023.1
2 parents caee734 + 22cccb9 commit 4b4fc27

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

nova/test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ def setUp(self):
317317
# all other tests.
318318
scheduler_utils.reset_globals()
319319

320+
# Wait for bare greenlets spawn_n()'ed from a GreenThreadPoolExecutor
321+
# to finish before moving on from the test. When greenlets from a
322+
# previous test remain running, they may attempt to access structures
323+
# (like the database) that have already been torn down and can cause
324+
# the currently running test to fail.
325+
self.useFixture(nova_fixtures.GreenThreadPoolShutdownWait())
326+
320327
def _setup_cells(self):
321328
"""Setup a normal cellsv2 environment.
322329

nova/tests/fixtures/nova.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,3 +1938,38 @@ def setUp(self):
19381938
'nova.compute.manager.ComputeManager.'
19391939
'_ensure_existing_node_identity',
19401940
mock.DEFAULT))
1941+
1942+
1943+
class GreenThreadPoolShutdownWait(fixtures.Fixture):
1944+
"""Always wait for greenlets in greenpool to finish.
1945+
1946+
We use the futurist.GreenThreadPoolExecutor, for example, in compute
1947+
manager to run live migration jobs. It runs those jobs in bare greenlets
1948+
created by eventlet.spawn_n(). Bare greenlets cannot be killed the same
1949+
way as GreenThreads created by eventlet.spawn().
1950+
1951+
Because they cannot be killed, in the test environment we must either let
1952+
them run to completion or move on while they are still running (which can
1953+
cause test failures as the leaked greenlets attempt to access structures
1954+
that have already been torn down).
1955+
1956+
When a compute service is stopped by Service.stop(), the compute manager's
1957+
cleanup_host() method is called and while cleaning up, the compute manager
1958+
calls the GreenThreadPoolExecutor.shutdown() method with wait=False. This
1959+
means that a test running GreenThreadPoolExecutor jobs will not wait for
1960+
the bare greenlets to finish running -- it will instead move on immediately
1961+
while greenlets are still running.
1962+
1963+
This fixture will ensure GreenThreadPoolExecutor.shutdown() is always
1964+
called with wait=True in an effort to reduce the number of leaked bare
1965+
greenlets.
1966+
1967+
See https://bugs.launchpad.net/nova/+bug/1946339 for details.
1968+
"""
1969+
1970+
def setUp(self):
1971+
super().setUp()
1972+
real_shutdown = futurist.GreenThreadPoolExecutor.shutdown
1973+
self.useFixture(fixtures.MockPatch(
1974+
'futurist.GreenThreadPoolExecutor.shutdown',
1975+
lambda self, wait: real_shutdown(self, wait=True)))

0 commit comments

Comments
 (0)