2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-10-20 14:45:45 +00:00

Start and stop the virsh console thread with the payload

Activation started an event thread whichever way the base handler had just
answered, so a refusal started one anyway and an already active console got a
second. activated alone cannot tell the two refusals apart, being true
already on the already active path, so the value from before the call decides.

Deactivation joined that thread on the event loop, where it could stall every
other session and its own response. The wait moves off the loop and is
bounded, and the thread is a daemon.
This commit is contained in:
Markus Hilger
2026-08-10 04:39:28 +02:00
parent 42ae44d5bf
commit bda403766e
+20 -2
View File
@@ -114,14 +114,32 @@ class LibvirtBmc(bmc.Bmc):
async def activate_payload(self, request, session):
# captured for stream_callback, which runs on a libvirt thread
self.asyncloop = asyncio.get_running_loop()
wasactive = self.activated
await super(LibvirtBmc, self).activate_payload(request, session)
if wasactive or not self.activated:
# the base handler refused: no io handler, or the domain is not
# running, so activated stayed false; or a console was already up,
# in which case activated was true before we asked and the thread
# for it is already running. Either way there is nothing to start.
return
self.run_console = True
self.sol_thread = threading.Thread(target=self.loop)
# virEventRunDefaultImpl can wait for an event that never comes, so
# this thread has no reliable end of its own
self.sol_thread.daemon = True
self.sol_thread.start()
async def deactivate_payload(self, request, session):
self.run_console = False
self.sol_thread.join()
if self.activated and self.sol_thread:
self.run_console = False
# Joining here would run on the event loop, and the thread sits in
# virEventRunDefaultImpl, which is documented as able to wait
# indefinitely: clearing run_console does not wake it. So wait off
# the loop, and not forever, rather than stall every other session
# and never send the response below.
await asyncio.get_running_loop().run_in_executor(
None, self.sol_thread.join, 5)
self.sol_thread = None
await super(LibvirtBmc, self).deactivate_payload(request, session)
async def iohandler(self, data):