Subject: Re: bug#47115: Grafts without deduplication can lead to breakage in Guile (was: Failure building grub-img.png when reconfiguring)

From: Mark H Weaver <[email-masked]>
Date: Tue, 16 Mar 2021 04:26:57 -0400

retitle 47115 Grafts without deduplication can lead to breakage in Guile
thanks

Hi Jack,

Jack Hill <[email-masked]> writes:

> I believe that I have identified the problematic difference in my 
> operating system config between my working and non-working hosts.

Thanks very much for your investigation.

> I am forced to conclude that running the guix-daemon with deduplication 
> disabled causes this build failure. Spooky!

Very interesting!

The only difference deduplication makes is that it (usually) causes
identical files in the store to be hard links to the same inode.

I have a new hypothesis:

Suppose that a reference to the original (ungrafted) version of some
library (e.g. libcairo or librsvg) has survived unchanged by the
grafting process.  This could lead to two copies of the same library
being loaded.  For example, I guess that libcairo is loaded by both
librsvg and by guile-cairo.  One of them might load the original
libcairo, and the other might load the replacement libcairo.

If the library is loaded twice, that could lead to each instance of the
library having its own dynamically-allocated type tags, which could lead
to this kind of error.

Here's the code where the error occurred:

  https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/build/svg.scm?id=bc16eacc99e801ac30cbe2aa649a2be3ca5c102a#n40

Guile uses 'cairo-create' (via guile-cairo) to create a cairo-context,
and then passes it to 'rsvg-handle-render-cairo', a 'librsvg' function,
which complains that the context argument has the wrong type.

If 'guile-cairo' was somehow using a different instance of 'libcairo'
than the one that 'librsvg' is linked to, that could explain what we're
seeing, because the two instances of 'libcairo' would have different
ideas of what the cairo-context tag should be.

However, *if* you have deduplication enabled, and *if* the library in
question doesn't contain any references that require rewrites due to
grafts, then these two copies of the library would most likely[*] be
hard links to the same inode.  Perhaps in that case, the run-time loader
recognizes that these are in fact the same library, and suppresses the
redundant load.

I don't know if this is what's happening, but it seems plausible.
Thoughts?

     Regards,
       Mark