Skip to content

Commit 3930269

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 3930269

2 files changed

Lines changed: 21 additions & 29 deletions

File tree

qubes/vm/dispvm.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -611,32 +611,45 @@ 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,
618+
qmemman_client.set_mem, # type: ignore[arg-type]
619+
{self.xid: 0},
618620
)
619-
tasks = [break_task, qmemman_task]
621+
tasks: list = [break_task, qmemman_task]
622+
result = None
623+
cancelled = False
624+
self.log.info("Setting qube memory to pref mem")
620625
try:
621626
# CI uses Python 3.12 and asynchronous iterator requires >=3.13
622627
# pylint: disable=not-an-iterable
623628
async for earliest_task in asyncio.as_completed(tasks):
624629
await earliest_task
625630
if earliest_task == break_task:
631+
self.log.info(
632+
"Canceling ballooning task, server might continue"
633+
)
634+
cancelled = True
626635
qmemman_task.cancel()
627636
else:
637+
result = qmemman_task.result()
628638
break_task.cancel()
629639
except asyncio.CancelledError:
630-
if qmemman_client:
631-
qmemman_client.close()
640+
pass
641+
except IOError as e:
642+
raise IOError("Failed to connect to qmemman: {!s}".format(e))
632643
except Exception as exc:
633644
self.log.warning(
634645
"Preload memory request before pause failed: %s", str(exc)
635646
)
636-
if qmemman_client:
637-
qmemman_client.close()
638647
raise
639648
finally:
649+
if qmemman_client.sock:
650+
qmemman_client.close()
651+
if not result or cancelled:
652+
self.log.warning("Failed to set memory")
640653
if self.preload_requested:
641654
raise qubes.exc.QubesVMCancelledPauseError(
642655
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)