diff options
author | Caleb Ristvedt <caleb.ristvedt@cune.org> | 2020-05-06 11:48:21 -0500 |
---|---|---|
committer | Caleb Ristvedt <caleb.ristvedt@cune.org> | 2020-05-07 05:56:01 -0500 |
commit | 37edbc91e34fb5658261e637e6ffccdb381e5271 (patch) | |
tree | fce0f68b538e242d650854806dbc59bfdebd3418 | |
parent | 5aa4d2dcf2f4f8786358feb45338893ed08a4cd9 (diff) | |
download | guix-37edbc91e34fb5658261e637e6ffccdb381e5271.tar.gz |
nar: 'finalize-store-file' follows proper store lock protocol.
* guix/nar.scm (finalize-store-file): check for deletion token when acquiring lock, write deletion token and delete lock file before releasing lock.
-rw-r--r-- | guix/nar.scm | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/guix/nar.scm b/guix/nar.scm index 29636aa0f8..0a6f59b09a 100644 --- a/guix/nar.scm +++ b/guix/nar.scm @@ -82,10 +82,28 @@ REFERENCES and DERIVER. When LOCK? is true, acquire exclusive locks on TARGET before attempting to register it; otherwise, assume TARGET's locks are already held." + ;; TODO: make this reusable + (define (acquire-lock file) + (let ((port (lock-file file))) + ;; There is an inherent race condition between opening the lock file and + ;; attempting to acquire the lock on it, and because we like deleting + ;; these lock files when we release them, only the first successful + ;; acquisition on a given lock file matters. To make it easier to tell + ;; when an acquisition is and isn't the first, the first to acquire it + ;; writes a deletion token (arbitrary character) prior to releasing the + ;; lock. + (if (zero? (stat:size (stat port))) + port + ;; if FILE is non-empty, that's because it contains the deletion + ;; token, so we aren't the first to acquire it. So try again! + (begin + (close port) + (acquire-lock file))))) + (with-database %default-database-file db (unless (path-id db target) (let ((lock (and lock? - (lock-file (string-append target ".lock"))))) + (acquire-lock (string-append target ".lock"))))) (unless (path-id db target) ;; If FILE already exists, delete it (it's invalid anyway.) @@ -102,6 +120,12 @@ held." #:deriver deriver)) (when lock? + (delete-file (string-append target ".lock")) + ;; Write the deletion token to inform anyone who acquires the lock + ;; on this particular file next that they aren't the first to + ;; acquire it, so they should retry. + (display "d" lock) + (force-output lock) (unlock-file lock)))))) (define (temporary-store-file) |