diff --git a/subiquity/server/controllers/filesystem.py b/subiquity/server/controllers/filesystem.py index c00b979cfb..40676a0c45 100644 --- a/subiquity/server/controllers/filesystem.py +++ b/subiquity/server/controllers/filesystem.py @@ -20,7 +20,6 @@ import logging import os import pathlib -import select import time from typing import Any, Callable, Dict, List, Optional, Union @@ -299,7 +298,7 @@ async def configured(self): ): self.app.base_model.source.search_drivers = not self.is_core_boot_classic() await super().configured() - self.stop_listening_udev() + self.stop_monitor() async def _mount_systems_dir(self, variation_name): self._source_handler = self.app.controllers.Source.get_handler(variation_name) @@ -1293,6 +1292,7 @@ async def _probe(self, *, context=None): finally: elapsed = time.time() - start log.debug(f"{short_label} probing took {elapsed:.1f} seconds") + self.start_monitor() break async def run_autoinstall_guided(self, layout): @@ -1456,21 +1456,26 @@ def start(self): self._start_task = schedule_task(self._start()) async def _start(self): - context = pyudev.Context() - self._monitor = pyudev.Monitor.from_netlink(context) - self._monitor.filter_by(subsystem="block") - self._monitor.enable_receiving() - self.start_listening_udev() + self.pyudev_context = pyudev.Context() await self._probe_task.start() - def start_listening_udev(self): + def start_monitor(self): + self._monitor = pyudev.Monitor.from_netlink(self.pyudev_context) + self._monitor.filter_by(subsystem="block") + self._monitor.start() loop = asyncio.get_running_loop() loop.add_reader(self._monitor.fileno(), self._udev_event) - def stop_listening_udev(self): + def stop_monitor(self): + if self._monitor is None: + return + loop = asyncio.get_running_loop() loop.remove_reader(self._monitor.fileno()) + del self._monitor + self._monitor = None + def ensure_probing(self): try: self._probe_task.start_sync() @@ -1479,21 +1484,10 @@ def ensure_probing(self): else: log.debug("Triggered Probert run on udev event") - def drain_udev(self): - # Drain the udev events in the queue -- if we stopped listening to - # allow udev to settle, it's good bet there is more than one event to - # process and we don't want to kick off a full block probe for each - # one. It's a touch unfortunate that pyudev doesn't have a - # non-blocking read so we resort to select(). - while select.select([self._monitor.fileno()], [], [], 0)[0]: - action, dev = self._monitor.receive_device() - log.debug("_udev_event %s %s", action, dev) - def _udev_event(self): - self.stop_listening_udev() + self.stop_monitor() cp = run_command(["udevadm", "settle", "-t", "0"]) - self.drain_udev() if cp.returncode != 0: log.debug("waiting 0.1 to let udev event queue settle") @@ -1501,7 +1495,6 @@ def _udev_event(self): loop.call_later(0.1, self._udev_event) return - self.start_listening_udev() self.ensure_probing() def make_autoinstall(self):