guix_mirror_bot pushed a commit to branch master
in repository guix.

commit 1a3d801d98f56cf3d915b21d17aa5f29b542ebb9
Author: Ludovic Courtès <[email protected]>
AuthorDate: Tue Aug 25 11:31:59 2026 +0200

    syscalls: Fix file descriptor leak in ‘lock-file’.
    
    Until now, calls to ‘lock-file’ with #:wait? #f throwing to 'flock-error 
would
    leak ‘port’.  The underlying file descriptor would be closed once ‘port’ is
    GC’d.  This change ensures the file descriptor is closed right away.
    
    * guix/build/syscalls.scm (lock-file): Catch 'flock-error around 
‘fcntl-flock’
    call.  Close port upon exception.  Clarify docstring.
    
    Signed-off-by: Ludovic Courtès <[email protected]>
---
 guix/build/syscalls.scm | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index e92bca7aaa..da3f56350f 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014-2025 Ludovic Courtès <[email protected]>
+;;; Copyright © 2014-2026 Ludovic Courtès <[email protected]>
 ;;; Copyright © 2015 David Thompson <[email protected]>
 ;;; Copyright © 2015 Mark H Weaver <[email protected]>
 ;;; Copyright © 2017 Mathieu Othacehe <[email protected]>
@@ -1582,13 +1582,20 @@ exception if it's already taken."
 
 (define* (lock-file file #:optional (mode "w0")
                     #:key (wait? #t))
-  "Wait and acquire an exclusive lock on FILE.  Return an open port according
-to MODE."
+  "Acquire an exclusive lock on FILE, waiting if WAIT? is true; when WAIT? is
+false and the lock cannot be acquired instantaneously, throw to 'flock-error.
+Return an open port according to MODE."
   (let ((port (open-file file mode)))
-    (fcntl-flock port
-                 (if (output-port? port) 'write-lock 'read-lock)
-                 #:wait? wait?)
-    port))
+    (catch 'flock-error
+      (lambda ()
+        (fcntl-flock port
+                     (if (output-port? port) 'write-lock 'read-lock)
+                     #:wait? wait?)
+        port)
+      (lambda (key . args)
+        ;; This is typically EAGAIN if WAIT? is false.
+        (close-port port)
+        (apply throw key args)))))
 
 (define (unlock-file port)
   "Unlock PORT, a port returned by 'lock-file', and close it."

Reply via email to