guix_mirror_bot pushed a commit to branch master
in repository guix.

commit 8a1a029f8fb6360d4b2c955e55f46b99f02a5c0f
Author: Ludovic Courtès <[email protected]>
AuthorDate: Tue Aug 25 11:34:59 2026 +0200

    cache: Avoid potential file descriptor leak.
    
    There fixes two cases where ‘maybe-remove-expired-cache-entries’ could leak
    ‘expiry-port’ (in which case the underlying file descriptor would be closed
    later, when ‘expiry-port’ gets GC’d.)
    
    * guix/cache.scm (maybe-remove-expired-cache-entries): When ‘obsolete?’
    returns false, explicitly close ‘expiry-port’.  When it returns true, catch
    errors around ‘seek’ block and close ‘expiry-port’ upon exception.  Remove
    ENOENT handling and comment that predates commit
    d921c742b774a9f0a016f3db6442d5c58a330c92.
    
    Signed-off-by: Ludovic Courtès <[email protected]>
    Merges: #10795
---
 guix/cache.scm | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/guix/cache.scm b/guix/cache.scm
index 5d8a0edbaa..c1a12b1762 100644
--- a/guix/cache.scm
+++ b/guix/cache.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013-2017, 2020-2021, 2023-2024 Ludovic Courtès <[email protected]>
+;;; Copyright © 2013-2017, 2020-2021, 2023-2024, 2026 Ludovic Courtès 
<[email protected]>
 ;;; Copyright © 2022 Simon Tournier <[email protected]>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -107,20 +107,23 @@ CLEANUP-PERIOD denotes the minimum time between two cache 
cleanups."
             0)
         +inf.0))
 
-  (when (obsolete? last-expiry-date now cleanup-period)
-    (remove-expired-cache-entries (cache-entries cache)
-                                  #:now now
-                                  #:entry-expiration entry-expiration
-                                  #:delete-entry delete-entry)
-    (catch 'system-error
-      (lambda ()
-        (seek expiry-port 0 SEEK_SET)
-        (truncate-file expiry-port 0)
-        (write (time-second now) expiry-port)
-        (unlock-file expiry-port))
-      (lambda args
-        ;; ENOENT means CACHE does not exist.
-        (unless (= ENOENT (system-error-errno args))
-          (apply throw args))))))
+  (if (obsolete? last-expiry-date now cleanup-period)
+      (begin
+        (remove-expired-cache-entries (cache-entries cache)
+                                      #:now now
+                                      #:entry-expiration entry-expiration
+                                      #:delete-entry delete-entry)
+        (catch #t
+          (lambda ()
+            (seek expiry-port 0 SEEK_SET)
+            (truncate-file expiry-port 0)
+            (write (time-second now) expiry-port)
+            ;; Note: 'unlock-file' closes EXPIRY-PORT.
+            (unlock-file expiry-port))
+          (lambda (key . args)
+            (close-port expiry-port)
+            (apply throw key args))))
+      (when expiry-port
+        (close-port expiry-port))))
 
 ;;; cache.scm ends here

Reply via email to