-
Notifications
You must be signed in to change notification settings - Fork 98
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
No detection of infinite recursion during evaluation of imports #1722
Comments
I think that wouldn't be too hard to detect. We could use the same mechanism as for thunks (blackholing), which already gives you something like: $ nickel repl
nickel> {x = y, y = x}
error: infinite recursion
┌─ <repl-input-0>:1:13
│
1 │ {x = y, y = x}
│ ^ recursive reference In fact, I believe we should just put imports inside thunks, so that their evaluation is shared anyway. Which would get this infinite recursion detection, as in the example above, for free. It's fun that you write:
I think it's just that when evaluating the loop, the Nix evaluator happens to run out of stack space, but it's not really what I would call detection. Maybe incidental detection? On the other hand, the loop runs in constant stack space in Nickel, which makes it just...loop. Anyway, those cases of simple loops can be easily detected, and I agree we should avoid eating all the CPU if we can. |
Note also that in general cyclic imports work fine in Nickel. That is, as long as there is no loop in the evaluation, you can import yourself. More precisely, as long as you don't need to evaluate the "import yourself" before producing a lazy value. For example:
$ nickel eval foo.ncl
{ unroll = fun _var => x, }
$ nickel repl
nickel> let foo = import "foo.ncl"
nickel> foo.unroll null
{ unroll = fun _var => x, }
nickel> (foo.unroll null).unroll null
{ unroll = fun _var => x, } This just gives you an infinite structure that you could write without imports as |
Yep, that's true, nix "detects" the loop by giving up, and hat's why it reports it as possible infinite recursion.
And, in fact, I was counting on that. I was actually experimenting with nickel to see it's viability for use in a package manager targeted specifically towards Ubuntu/Debian. Some packages would require dependencies to be defined in nickel, and the main file of a repository would reference all the packages in it, so this would possibly require a cyclical import. The only thing really missing here is external/remote imports (tho I've seen you guys have been recently discussing about it), but I could manage to do that in a custom fork if I need to while it is not supported here on upstream. |
Indeed, cf #1585. By the way, recent commits to master (#1716, #1721 to be merged) add a |
True, |
Describe the bug
When a Nickel file attempts to do recursive imports, the evaluation process may hang indefinitely, and sometimes consumes all available RAM. This could happen due to user error.
To Reproduce
nickel eval ./recursive_import.ncl
Expected behavior
Nickel should detect recursive imports and gracefully handle them, either by preventing the evaluation recursion or by providing a clear error message, to avoid hanging during evaluation and consuming excessive resources.
Environment
Additional context
The example above is a simplified way of showing this bug. This issue was found during testing on my use case, with 2 files, due to a typo:
This wouldn't necessarily cause an evaluation recursion by itself, but I mistyped something and the imports did result in a recursion, and that crashed my PC by consuming all the RAM (and swap).
In comparison, Nix detects such recursions and reports it with the following error:
$ nix eval --file ./recursive_import.nix error: stack overflow (possible infinite recursion)
The text was updated successfully, but these errors were encountered: