hercules-ci / flake-parts

❄️ Simplify Nix Flakes with the module system
https://flake.parts
MIT License
721 stars 41 forks source link

Segmentation fault during flake evaluation using overlayAttrs #140

Closed remi-gelinas closed 1 year ago

remi-gelinas commented 1 year ago

I'm trying to leverage overlayAttrs and easyOverlay to split out some of my overlays into submodules, but I've hit a weird issue. In this commit specifically, when I added these 4 imported submodules to add stuff to my default overlay, I start getting segfaults in my shell when I do any kind of flake evaluation. Loading the flake into nix repl, nix flake show, anything that results in a full flake eval segfaults.

Oddly enough, when I remove these 4 imports, everything works fine. Is there some kind of memory limit I'm hitting trying to use too many nested submodules?

Currently it segfaults when evaluating the pre-commit checks, but if you disable the checks that their module creates, it then segfaults trying to evaluate the default devshell.

roberth commented 1 year ago

Well, a segfault should never happen. Nix should report the exact issue, whether that's OOM, or a stack overflow, or whatever else, so this behavior is at least a Nix bug, but quite possibly triggered by something in your code. As far as I know, the most likely causes for a segfault are

So if you could try with nix master and/or post more details to reproduce this, we may be able to narrow this down.

Note to self: rename easyOverlay.

srid commented 1 year ago

Related? https://github.com/srid/nixos-config/issues/31

(I'm not using overlayAttrs)

remi-gelinas commented 1 year ago

Well, a segfault should never happen. Nix should report the exact issue, whether that's OOM, or a stack overflow, or whatever else, so this behavior is at least a Nix bug, but quite possibly triggered by something in your code. As far as I know, the most likely causes for a segfault are

* Running on macOS; should be fixed in 2.15.0, which is _very_ recent; try with `nix run nix -- repl` for example? (runs nix master).

* Broken stack overflow detection. This currently relies exclusively on a segfault handler for getting reported.

* Some other problem; can't exclude that, sadly.

So if you could try with nix master and/or post more details to reproduce this, we may be able to narrow this down.

Note to self: rename easyOverlay.

After trying with nix master as you suggested, loading into the repl worked, and loading the flake worked. Evaluating debug.flake.darwinConfigurations.M1 however, segfaulted again. The exact error Fish returns is SIGSEGV (Address boundary error), whereas doing it in bash throws back Segmentation fault: 11.

I'm attempting to build this on MacOS Ventura, on an Intel Macbook, so on x86_64-darwin - that said, before introducing flake-parts, I was able to build configurations for either architecture just fine (not run anything from them of course, but just build the derivation).

If you clone my flake in my remi-gelinas/flake-parts branch, HEAD still has the issue. If you enter a repl, load the flake, and evaluate the M1 darwinConfiguration, devShells.default, either throws the segfault. Like I said, removing the several imports in overlays/flake-module.nix fixes the problem, so there's probably something in those that it doesn't like.

EDIT: Ninja edit to include the link to the repo and branch directly, found here :)

roberth commented 1 year ago

So it was both. On a linux machine:

nix-repl> debug.flake.darwinConfigurations.M1
error: stack overflow (possible infinite recursion)

It's probably because you're both importing easyOverlay and defining pkgs yourself. That's probably conflicting. I'm surprised that it's not an infinite recursion. Nix can't give a stack trace for stack overflows yet, so I can only speculate about the cause for now.

I'll demote and clarify easyOverlay right now and I think the best solution for you is either to avoid overlays, as more often than not they're not needed, or you could define it as usual in flake.overlays.default; basically like you did before.

remi-gelinas commented 1 year ago

That makes sense. I thought from the docs that easyOverlay just added the final arg for modules, but it makes sense that it would provide pkgs itself to facilitate that. Out of curiosity, what solution would you recommend for providing multiple package sets like I'm doing with overlays? If I wanted to avoid overlays, that is, and do it as idiomatically as I can with flake-parts?

Side-note, I'll test on a Linux machine from now on when I hit these.

roberth commented 1 year ago

providing multiple package sets

Are you providing them to some other flake or is it for internal organization? In the latter case you get the same effect by defining packages in packages. Things that depend on your custom packages (including other custom packages) could get them from config.packages. pkgs.callPackage won't be aware of those, but you can pass them like so pkgs.callPackage ./some-file.nix { inherit (config.packages) my-dep; }.

If that gets annoying, you could define myCallPackage = pkgs.newScope config.packages; in a let binding, option, or module argument. That way the package arguments are selected from config.packages first and pkgs second.

remi-gelinas commented 1 year ago

Mostly just for internal organization, for when I need to pull unstable/master versions of packages specifically and use stable by default for example. Since importing package sets aren't a package type, I can't put them in config.packages or perSystem.packages, but I ended up just adding options for perSystem.lib to hold them, and it works a treat.

This is a much cleaner method of doing this than putting everything into overlays. Thank you!