Skip to content

Commit 774fb6b

Browse files
committed
Close qmemman client with correct handler
QMemmanClient is instantiated from the same method that is calling it as a task, so it guarantees access to the close() method, else, it may not be able to close the connection properly if the task is cancelled, as the result() will not contain the instance, but CancelledError. For: QubesOS/qubes-issues#1512
1 parent 2488f2b commit 774fb6b

2 files changed

Lines changed: 18 additions & 28 deletions

File tree

qubes/vm/dispvm.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -611,32 +611,43 @@ async def on_domain_pre_paused(self, event, **kwargs) -> None:
611611
return
612612
if self.preload_requested:
613613
return
614-
qmemman_client = None
615614
break_task = asyncio.create_task(self.preload_requested_event.wait())
616-
qmemman_task = asyncio.get_event_loop().run_in_executor(
617-
None, self.set_mem
615+
qmemman_client = qubes.qmemman.client.QMemmanClient()
616+
qmemman_task = asyncio.get_running_loop().run_in_executor(
617+
None, qmemman_client.set_mem, {self.xid: 0}
618618
)
619619
tasks = [break_task, qmemman_task]
620+
result = None
621+
cancelled = False
622+
self.log.info("Setting qube memory to pref mem")
620623
try:
621624
# CI uses Python 3.12 and asynchronous iterator requires >=3.13
622625
# pylint: disable=not-an-iterable
623626
async for earliest_task in asyncio.as_completed(tasks):
624627
await earliest_task
625628
if earliest_task == break_task:
629+
self.log.info(
630+
"Canceling ballooning task, server might continue"
631+
)
632+
cancelled = True
626633
qmemman_task.cancel()
627634
else:
635+
result = qmemman_task.result()
628636
break_task.cancel()
629637
except asyncio.CancelledError:
630-
if qmemman_client:
631-
qmemman_client.close()
638+
pass
639+
except IOError as e:
640+
raise IOError("Failed to connect to qmemman: {!s}".format(e))
632641
except Exception as exc:
633642
self.log.warning(
634643
"Preload memory request before pause failed: %s", str(exc)
635644
)
636-
if qmemman_client:
637-
qmemman_client.close()
638645
raise
639646
finally:
647+
if qmemman_client.sock:
648+
qmemman_client.close()
649+
if not result or cancelled:
650+
self.log.warning("Failed to set memory")
640651
if self.preload_requested:
641652
raise qubes.exc.QubesVMCancelledPauseError(
642653
self,

qubes/vm/qubesvm.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,27 +2097,6 @@ def request_mem(self, mem_required=None):
20972097

20982098
return qmemman_client
20992099

2100-
def set_mem(self):
2101-
"""
2102-
Balloon qube to preferred memory, which is just enough for it to be
2103-
running without problems.
2104-
"""
2105-
if not qmemman_present or self.maxmem == 0:
2106-
return None
2107-
2108-
self.log.info("Setting qube memory to pref mem")
2109-
qmemman_client = qubes.qmemman.client.QMemmanClient()
2110-
try:
2111-
result = qmemman_client.set_mem({self.xid: 0})
2112-
except IOError as e:
2113-
raise IOError("Failed to connect to qmemman: {!s}".format(e))
2114-
2115-
if not result:
2116-
qmemman_client.close()
2117-
self.log.warning("Failed to set memory")
2118-
2119-
return qmemman_client
2120-
21212100
@staticmethod
21222101
async def start_daemon(*command, input=None, **kwargs):
21232102
"""Start a daemon for the VM

0 commit comments

Comments
 (0)