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