<div dir="ltr"><div>> Guix also controls environment variables (which I don't think you talk about in your paper) to ensure the same initial state.</div><div><br></div><div>Yeah, we didn't really come up with a principled approach to handling env vars. Inside the container, we start with the default container-set env vars, but this itself may leak more information about the system than we would like. On the other hand, unsettting too many env vars that programs expect to be set often results in weird, hard to track down errors.</div><div><br></div><div>> We avoid a lot of the non-determinism issues other package managers are
struggling with, but we still have some and we try to fix them one by
one when we encounter them</div><div><br></div><div>I see, does Guix maintain a list somewhere of all sources of nondeterminism that the project has come across? DRB has something like this via <a href="https://tests.reproducible-builds.org/debian/reproducible.html" target="_blank">https://tests.reproducible-builds.org/debian/reproducible.html</a></div><div><br></div><div>> so we don't prevent reading a file timestamp, current time or issues due
to filesystem ordering. You seem to have a solution for these things
that are probably our greatest cause of non determinism now, so I'm
really looking forward to seeing your implementation and try and port it
to guix if it is practical</div><div>Yeah, the main approach for this would be to intercept some subset of filesystem system calls and ensure results returned for various values (e.g. timestamps) are deterministic. This itself requires some finesse, as clever programs like autotools `./configure` create an empty file, and compare the mtime or ctime of the file, versus the current time of the system clock to check for clock skews (and crashes if it doesn't like what it sees). Filesystem file ordering is handled by sorting the results of the readdir system call before hand (this means reading the entire dir ahead of time). A FUSE layer can also handle file ordering, but IMO not worth the slow down of all IO operations to the filesystem.</div><div><br></div><div>> <span></span>
I know, I'm also in academia :) (I'm a post-doc at yale now, I should
update my webpage). I tend to prefer perfect and complete solutions, but
if we can already improve things, it's great!</div><div><br></div><div>That's super cool!<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Feb 12, 2020 at 1:27 PM Julien Lepiller <<a href="mailto:julien@lepiller.eu" target="_blank">julien@lepiller.eu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Le 12 février 2020 11:50:11 GMT-05:00, Omar Navarro Leija <<a href="mailto:omarsa@seas.upenn.edu" target="_blank">omarsa@seas.upenn.edu</a>> a écrit :<br>
>Hello Julien,<br>
><br>
>I'm glad you enjoyed the work!<br>
><br>
>Your understanding of DetTrace is correct. Our container abstraction is<br>
>very lightweight in the sense that we just piggyback off Linux<br>
>namespaces +<br>
>chroot to provide isolation. Currently, to provide reproducibility,<br>
>someone<br>
>using DetTrace should download a chroot image (e.g. via debootstrap)<br>
>and<br>
>use this as the canonical filesystem image to use for the build. This<br>
>is a<br>
>bit clunky, and I believe it is not a 100% satisfactory solution. I<br>
>don't<br>
>know of any other ways to "normalize" the filesystem environment<br>
>though.<br>
><br>
>This may seem a little heavy handed, so I'm curious how Guix handles a<br>
>build process that tries to read arbitrary filessystem data? I'm<br>
>reading<br>
>more about Guix now, so I'll have smarter things to say about it later<br>
>(hopefully).<br>
<br>
Guix builds packages in an isolated environment, with user namespaces: the build always happens in $TMPDIR/guix-build-package-n (normalized to /tmp/guix-build-package-0 in the environment), with access to declared inputs in the store (built with this process or downloaded after checking the hash of their content). The user is normalized to guix-build and uid and gid are set to 0 iirc. Guix also controls environment variables (which I don't think you talk about in your paper) to ensure the same initial state.<br>
<br>
The initial filesystem is therefore composed of the inputs, sources and build script, in /gnu/store that were built reproducibly (hopefully) and an empty directory in /tmp. Any machine can reproduce this environment bit-to-bit if: they use the same architecture, they use the same guix git commit, they build the same package, they could download or build every input (there's guix time-machine to re-create something from a specific commit). The store is more or less an append-only structure where you can't do any overriding, which ensures that same inputs=same outputs.<br>
<br>
I'm not sure we actually isolate anything in the store, but store items have a hash that's computed from inputs, sources and other stuff. It's not possible to guess that unless you have a direct reference (although an adversarial process could do a nasty ls I suppose).<br>
<br>
However, there is no other mechanism, so we don't prevent reading a file timestamp, current time or issues due to filesystem ordering. You seem to have a solution for these things that are probably our greatest cause of non determinism now, so I'm really looking forward to seeing your implementation and try and port it to guix if it is practical. We avoid a lot of the non-determinism issues other package managers are struggling with, but we still have some and we try to fix them one by one when we encounter them.<br>
<br>
>For Dettrace we set out to see if it was feasible to create a 100%<br>
>(foolproof) dynamic determinism enforcement system. I believe we<br>
>succeeded<br>
>at this goal (modulo some CPU instructions). However, I don't believe<br>
>the<br>
>full-proof solution is necessary or practical (tangent: our solution<br>
>attempts to be foolproof for mostly academic reasons, not practical<br>
>concerns about solving real problems, this is part of the fun of being<br>
>in<br>
>academia).<br>
<br>
I know, I'm also in academia :) (I'm a post-doc at yale now, I should update my webpage). I tend to prefer perfect and complete solutions, but if we can already improve things, it's great!<br>
<br>
><br>
>The point being: we attempt to sequentialize execution of threads, this<br>
>is<br>
>extremely difficult, and we can't do it properly. The biggest sources<br>
>of<br>
>unsupported packages (more details in the paper!) are Java, sockets,<br>
>and<br>
>intra-process signals. Java always ends up deadlocking due to our<br>
>attempts<br>
>to sequentialize thread execution in the JVM. With our current methods<br>
>I<br>
>don't think this can ever work properly.<br>
><br>
>Not all is lost though: I don't expect package builds to be<br>
>nondeterministic from thread scheduling, sockets, or signals. So the<br>
>simple<br>
>solution is just to allow these things to happen in DetTrace and call<br>
>it<br>
>good enough. We still get all the other benefits of DetTrace but relax<br>
>the<br>
>paranoia and thus allow a wider set of packages to build. DetTrace<br>
>could<br>
>certainly be modified to support this.<br>
><br>
>I don't have any immediate plans to improve this, but would certainly<br>
>not<br>
>be against it either. I like to think the biggest contribution of<br>
>DetTrace<br>
>toward the reproducible builds effort is the ideas and methods, rather<br>
>than<br>
>the implementation.<br>
><br>
>I'll definitely let you know when it is available, the implementation<br>
>is<br>
>not as robust as it could be. So I want to set expectations<br>
>accordingly!<br>
<br>
Thank you!<br>
<br>
><br>
>Omar<br>
><br>
</blockquote></div>