summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2026-08-25 11:34:59 +0200
committerLudovic Courtès <ludo@gnu.org>2026-08-27 14:41:25 +0200
commit8a1a029f8fb6360d4b2c955e55f46b99f02a5c0f (patch)
tree8bc26efd5950237126cd67897169284baac09f29
parent1a3d801d98f56cf3d915b21d17aa5f29b542ebb9 (diff)
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 <ludo@gnu.org> Merges: #10795
-rw-r--r--guix/cache.scm35
1 files changed, 19 insertions, 16 deletions
diff --git a/guix/cache.scm b/guix/cache.scm
index 5d8a0edbaab..c1a12b17620 100644
--- a/guix/cache.scm
+++ b/guix/cache.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2013-2017, 2020-2021, 2023-2024 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2013-2017, 2020-2021, 2023-2024, 2026 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2022 Simon Tournier <zimon.toutoune@gmail.com> 3;;; Copyright © 2022 Simon Tournier <zimon.toutoune@gmail.com>
4;;; 4;;;
5;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
@@ -107,20 +107,23 @@ CLEANUP-PERIOD denotes the minimum time between two cache cleanups."
107 0) 107 0)
108 +inf.0)) 108 +inf.0))
109 109
110 (when (obsolete? last-expiry-date now cleanup-period) 110 (if (obsolete? last-expiry-date now cleanup-period)
111 (remove-expired-cache-entries (cache-entries cache) 111 (begin
112 #:now now 112 (remove-expired-cache-entries (cache-entries cache)
113 #:entry-expiration entry-expiration 113 #:now now
114 #:delete-entry delete-entry) 114 #:entry-expiration entry-expiration
115 (catch 'system-error 115 #:delete-entry delete-entry)
116 (lambda () 116 (catch #t
117 (seek expiry-port 0 SEEK_SET) 117 (lambda ()
118 (truncate-file expiry-port 0) 118 (seek expiry-port 0 SEEK_SET)
119 (write (time-second now) expiry-port) 119 (truncate-file expiry-port 0)
120 (unlock-file expiry-port)) 120 (write (time-second now) expiry-port)
121 (lambda args 121 ;; Note: 'unlock-file' closes EXPIRY-PORT.
122 ;; ENOENT means CACHE does not exist. 122 (unlock-file expiry-port))
123 (unless (= ENOENT (system-error-errno args)) 123 (lambda (key . args)
124 (apply throw args)))))) 124 (close-port expiry-port)
125 (apply throw key args))))
126 (when expiry-port
127 (close-port expiry-port))))
125 128
126;;; cache.scm ends here 129;;; cache.scm ends here