Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make nix/unpack-channel.nix a builtin builder #2748

Merged
merged 23 commits into from
Nov 29, 2019
Merged

Conversation

edolstra
Copy link
Member

This rewrites the builder of <nix/unpack-channel.nix> in C++ and Rust. Previously the builder was a shell script. Since this was the only builder that was still a shell script, this allows us to get rid of the dependency on bash, coreutils, tar, xz, bzip2 etc., reducing Nix's closure size.

This is mostly an experiment in using Rust in Nix. It uses the tar crate to do the parsing of tar files.

auto source = sinkToSource([&](Sink & sink) {
auto decompressor =
hasSuffix(src, ".bz2") ? makeDecompressionSink("bzip2", sink) :
hasSuffix(src, ".xz") ? makeDecompressionSink("xz", sink) :
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No gzip?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we currently lack gzip support in compression.cc. Probably not a big deal since our channels don't use it, but it would be nice to add.

[path of cat, mkdir, etc.]),
coreutils=$withval, coreutils=$(dirname $cat))
AC_SUBST(coreutils)
AC_SUBST(coreutils, [$(dirname $(type -p cat))])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For cross compilation purposes, it is nice to let this be a flag. These should just be runtime deps AFAICT. See NixOS/nixpkgs#58104

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, with this PR, it's now only used during the tests, which I assume cannot be run in a cross-compiled build anyway?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true right now

configure.ac Outdated Show resolved Hide resolved
nix-rust/src/lib.rs Outdated Show resolved Hide resolved
@lovesegfault
Copy link
Member

This is blocking on getting Nix working well on a number of Linux distros. As an employee of a Nix-based company, it'd be really nice if this landed so I can go back to doing work on my machine, which I haven't been able to for a while now.

@edolstra edolstra changed the title [WIP] Make nix/unpack-channel.nix a builtin builder Make nix/unpack-channel.nix a builtin builder Jul 5, 2019
@Janiczek
Copy link

Janiczek commented Jul 9, 2019

@lovesegfault (I'm unaffiliated with Nix, but...) If your company is that dependent on Nix, maybe it could fund some dedicated time from the Nix developers on this issue?

@lovesegfault
Copy link
Member

@Janiczek We definitely should, I'll see what I can do.

@illegalprime
Copy link
Member

I think this fixes NixOS/nixpkgs#58104 as I understand it. Thanks for this!

Also, fetchGit now runs in O(1) memory since we pipe the output of
'git archive' directly into unpackTarball() (rather than first reading
it all into memory).
https://hydra.nixos.org/build/107467517

Seems that on i686-linux, gcc and rustc disagree on how to return
1-word structs: gcc has the caller pass a pointer to the result, while
rustc has the callee return the result in a register. Work around this
by using a bare pointer.
This is a hack to fix the build on macOS, which was failing because
libnixrust.a contains compiler builtins that clash with
libclang_rt.osx.a. There's probably a better solution...

https://hydra.nixos.org/build/107473280
@edolstra edolstra merged commit f102d79 into NixOS:master Nov 29, 2019
@edolstra edolstra deleted the rust branch November 29, 2019 18:33
Copy link
Contributor

@puckipedia puckipedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that the code's been merged for more than a week now, but I still felt the need to post some opinions; I didn't actually assume this code would be merged any time, as i did not regard it as production-ready, with many of the FIXMEs strewn about.

unsafe {
let size = std::mem::size_of::<T>();
let ptr = libc::malloc(size);
*(ptr as *mut T) = t; // FIXME: probably UB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed UB, as you're dereferencing an arbitrary value (which could be illegal for this T); this could cause double-frees, arbitrary UAFs, segfaults, etc.


extern "C" {
#[allow(improper_ctypes)] // YOLO
fn make_error(s: &str) -> CppException;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fat pointers are, afaik, not FFI-safe at all, and may just do the entire wrong thing.

namespace rust {

// Depending on the internal representation of Rust slices is slightly
// evil...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is. There's zero guarantee that the internal representation of a slice will look like this.

}
};

/* C++ representation of Rust's Result<T, CppException>. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that there's no guarantee that the enum actually is represented like this; Rust does a lot of niche filling and depending on the type of T the tag might just disappear.

source: foreign::Source,
dest_dir: &str,
) -> CBox<Result<(), error::CppException>> {
CBox::new(tarfile::unpack_tarfile(source, dest_dir).map_err(|err| err.into()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning a CBox<Result<(), error::CppException>> seems kind of useless, why not just return a pointer to a CppException directly? This also saves allocations in the best case, and is actually FFI-safe.

@kaii-zen
Copy link
Contributor

kaii-zen commented Dec 9, 2019

Is this merged to the flakes branch? I can't seem to be able to fetch flakes that aren't already in the store. Getting the suspicious-looking:

unpacking 'https://api.github.com/repos/NixOS/hydra/tarball/47797576838974c8209536b67bb45e953a50900f'...
error: numeric field did not have utf-8 text: �ps�� when getting cksum for �
(use '--show-trace' to show detailed location information)
error: evaluation of the deployment specification failed

@Ericson2314
Copy link
Member

CC @edef1c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants