From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
To: ludo@gnu.org (Ludovic Courtès)
Cc: h.goebel@crazy-compilers.com,
Eelco Dolstra <eelco.dolstra@logicblox.com>,
25018-done@debbugs.gnu.org
Subject: bug#25018: GC incorrectly removes the temporary root file of the calling process
Date: Fri, 07 Oct 2022 16:59:20 -0400 [thread overview]
Message-ID: <87pmf34afr.fsf@gmail.com> (raw)
In-Reply-To: <87d1hl55ur.fsf@gnu.org> ("Ludovic Courtès"'s message of "Thu, 24 Nov 2016 15:07:24 +0100")
Hi Ludo,
ludo@gnu.org (Ludovic Courtès) writes:
> Hello,
>
> The ‘readTempRoots’ function in gc.cc has this:
>
> /* Try to acquire a write lock without blocking. This can
> only succeed if the owning process has died. In that case
> we don't care about its temporary roots. */
> if (lockFile(*fd, ltWrite, false)) {
> printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path);
> unlink(path.c_str());
>
> There’s a thinko here: locking the file also succeeds when the lock is
> already held by the calling process.
>
> In that case, this code ends up removing the temporary root file of
> calling process, which is bad. Here’s a sample session:
>
> scheme@(guile-user)> ,use(guix)
> scheme@(guile-user)> (define s (open-connection))
> scheme@(guile-user)> (current-build-output-port (current-error-port))
> $2 = #<output: file /dev/pts/9>
> scheme@(guile-user)> (set-build-options s #:verbosity 10)
> $3 = #t
> scheme@(guile-user)> (add-text-to-store s "foo" "bar!")
> acquiring global GC lock `/var/guix/gc.lock'
> acquiring read lock on `/var/guix/temproots/4259'
> acquiring write lock on `/var/guix/temproots/4259'
> downgrading to read lock on `/var/guix/temproots/4259'
> locking path `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
> lock acquired on `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo.lock'
> `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo' has hash `c756ef12a70bad10c9ac276ecd1213ea7cc3a2e6c462ba47e4f9a88756a055d0'
> lock released on `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo.lock'
> $4 = "/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo"
> scheme@(guile-user)> (delete-paths s (list $4))
> acquiring global GC lock `/var/guix/gc.lock'
> finding garbage collector roots...
> executing `/gnu/store/l99rkv2713nl53kr3gn4akinvifsx19h-guix-0.11.0-3.7ca3/libexec/guix/list-runtime-roots' to find additional roots
> […]
> reading temporary root file `/var/guix/temproots/4259'
> removing stale temporary roots file `/var/guix/temproots/4259'
> […]
> considering whether to delete `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
> | invalidating path `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
> | deleting `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
> | recursively deleting path `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
> | | /gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo
> deleting `/gnu/store/trash'
> recursively deleting path `/gnu/store/trash'
> | /gnu/store/trash
> deleting unused links...
> deleting unused link `/gnu/store/.links/1l2ml1b8ga7rwi3vlqn4wsic6z7a2c9csvi7mk4i1b8blw9fymn7'
> note: currently hard linking saves 6699.22 MiB
> $5 = ("/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo")
> $6 = 4096
>
> Notice the “removing stale temporary roots file” message.
>
> Eelco: shouldn’t it be changed along the lines of the attached path?
>
>
> Thanks,
> Ludo’.
>
> diff --git a/nix/libstore/gc.cc b/nix/libstore/gc.cc
> index 72eff52..d92388f 100644
> --- a/nix/libstore/gc.cc
> +++ b/nix/libstore/gc.cc
> @@ -2,6 +2,7 @@
> #include "misc.hh"
> #include "local-store.hh"
>
> +#include <string>
> #include <functional>
> #include <queue>
> #include <algorithm>
> @@ -225,10 +226,10 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
> //FDPtr fd(new AutoCloseFD(openLockFile(path, false)));
> //if (*fd == -1) continue;
>
> - /* Try to acquire a write lock without blocking. This can
> - only succeed if the owning process has died. In that case
> - we don't care about its temporary roots. */
> - if (lockFile(*fd, ltWrite, false)) {
> + /* Try to acquire a write lock without blocking. This can only
> + succeed if the owning process has died, in which case we don't care
> + about its temporary roots, or if we are the owning process. */
> + if (i.name != std::to_string(getpid()) && lockFile(*fd, ltWrite, false)) {
> printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path);
> unlink(path.c_str());
> writeFull(*fd, "d");
>
I'm not Eelco, but your change LGTM. Note that the upstream version
still uses the original code [0].
I've installed the change, tested that it had the expected result:
--8<---------------cut here---------------start------------->8---
reading temporary root file `/var/guix/temproots/8386'
waiting for read lock on `/var/guix/temproots/8386'
got temporary root `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
considering whether to delete `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo'
| cannot delete `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo' because it's a root
| cannot delete `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo' because it's still reachable
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
ERROR:
1. &store-protocol-error:
message: "cannot delete path `/gnu/store/0siy93lggjw7sfdg8gsvrzafaa974h2d-foo' since it is still alive"
status: 1
--8<---------------cut here---------------end--------------->8---
and pushed!
Closing.
[0] https://github.com/NixOS/nix/blob/master/src/libstore/gc.cc#L194
--
Thanks,
Maxim
next prev parent reply other threads:[~2022-10-07 21:00 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-24 14:07 bug#25018: GC incorrectly removes the temporary root file of the calling process Ludovic Courtès
2022-10-07 20:59 ` Maxim Cournoyer [this message]
2022-10-10 8:01 ` Ludovic Courtès
2022-10-10 10:29 ` Maxime Devos
2022-10-10 14:53 ` Ludovic Courtès
2022-10-14 20:30 ` Ludovic Courtès
2022-10-17 1:25 ` Maxim Cournoyer
2022-10-17 8:51 ` Ludovic Courtès
2022-10-18 15:33 ` Maxim Cournoyer
2022-10-10 17:24 ` bug#25018: Broken test suite Ryan Sundberg via Bug reports for GNU Guix
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87pmf34afr.fsf@gmail.com \
--to=maxim.cournoyer@gmail.com \
--cc=25018-done@debbugs.gnu.org \
--cc=eelco.dolstra@logicblox.com \
--cc=h.goebel@crazy-compilers.com \
--cc=ludo@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).