diff mbox series

[15/15] buildstats: close proc/disk log files via weakref.finalize safety net

Message ID 20260909215337.89106-16-adrian.freihofer@siemens.com
State New
Headers show
Series devtool ide-sdk: support booting from NFS, VSCode clangd | expand

Commit Message

AdrianF Sept. 9, 2026, 9:53 p.m. UTC
From: Adrian Freihofer <adrian.freihofer@siemens.com>

SystemStats.close() is normally invoked by the buildstats.bbclass handler
on bb.event.BuildCompleted, but that event is skipped for internal,
event-less task runs (e.g. tinfoil's run_prepared_task(), used by
devtool ide-sdk). Without a BuildCompleted event, the open proc/disk log
files were only closed implicitly at GC/interpreter-exit time, causing a
ResourceWarning for leaked file handles.

Register a weakref.finalize() callback at construction time as a safety
net. close() now just triggers the finalizer, which is idempotent and
keeps no reference back to SystemStats itself.

AI-Generated: Uses GitHub Copilot

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
 meta/lib/oe/buildstats.py | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/meta/lib/oe/buildstats.py b/meta/lib/oe/buildstats.py
index db3d26afb8..56228246e4 100644
--- a/meta/lib/oe/buildstats.py
+++ b/meta/lib/oe/buildstats.py
@@ -10,6 +10,7 @@ 
 import os
 import time
 import re
+import weakref
 import bb.event
 from collections import deque
 
@@ -56,6 +57,12 @@  class SystemStats:
                     destfile = os.path.join(bsdir, '%sproc_%s.log' % ('reduced_' if handler else '', filename))
                 self.proc_files.append((filename, open(destfile, 'ab'), handler))
         self.monitor_disk = open(os.path.join(bsdir, 'monitor_disk.log'), 'ab')
+        # Safety net: normally close() is called when bb.event.BuildCompleted
+        # fires, but that event is skipped for internal, event-less task runs
+        # (e.g. tinfoil's run_prepared_task()). Without this, the open files
+        # would only get closed implicitly at GC/interpreter-exit time,
+        # triggering a ResourceWarning.
+        self._finalizer = weakref.finalize(self, self._close_files, self.proc_files, self.monitor_disk)
         # Last time that we sampled /proc data resp. recorded disk monitoring data.
         self.last_proc = 0
         self.last_disk_monitor = 0
@@ -81,8 +88,12 @@  class SystemStats:
         self.net_stats = {}
 
     def close(self):
-        self.monitor_disk.close()
-        for _, output, _ in self.proc_files:
+        self._finalizer()
+
+    @staticmethod
+    def _close_files(proc_files, monitor_disk):
+        monitor_disk.close()
+        for _, output, _ in proc_files:
             output.close()
 
     def _reduce_meminfo(self, time, data, filename):