From 858fecb9b52bad838095ee365a4c1b0804556b09 Mon Sep 17 00:00:00 2001
From: Dan Bungert <daniel.bungert@canonical.com>
Date: Mon, 25 Sep 2023 17:11:21 -0600
Subject: [PATCH] even more aggressive

---
 subiquity/server/controllers/filesystem.py | 40 ++++++++++------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/subiquity/server/controllers/filesystem.py b/subiquity/server/controllers/filesystem.py
index c00b979cfb..90635f0f52 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,29 @@ 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):
+        log.debug("start_monitor")
+        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:
+            log.debug("stop_monitor - ignoring non-started monitor")
+            return
+
+        log.debug("stop_monitor")
         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 +1487,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 +1498,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):