-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Segfault in nimlangserver when -d:nimOptIter
is defined
#24094
Comments
When trying to reproduce I didn't get a stacktrace, only "out of memory". |
hmm In what OS are you testing? Do you get that same issue in There is |
Windows; no; with refc/arc it gives the segfault exit code (as opposed to orc). The above stacktrace should only be reachable in refc from my understanding since I'm out of my depth here, I thought maybe a type graph change or cycle was the cause, I also don't know where a deep copy could be happening |
@ringabout @metagn Please bisect it. |
I got the stacktrace in MacOs. Yes, |
This comment was marked as outdated.
This comment was marked as outdated.
The type that proc foo() =
let x = 123
iterator bar2(): int {.closure.} =
yield x
proc bar() =
let z = bar2
for y in z(): # just doing bar2() gives param not in env: x
echo y
bar()
foo() The output of this is now Changing iterator foo(): int {.closure.} =
let x = 123
iterator bar2(): int {.closure.} =
yield x
proc bar() =
let z = bar2
for y in z():
echo y
bar()
yield x
for x in foo(): echo x And this used to work and give the correct output but now also segfaults: iterator foo(): int {.closure.} =
let x = 123
proc bar() =
echo x
iterator bar2(): int {.closure.} =
bar()
yield x
for y in bar2():
yield y
for x in foo(): echo x I wouldn't even know where to start to try and minimize the segfault in nimlangserver, but the first closure proc/iterator mixing example seems realistic to encounter in async code. It was broken before too but maybe it zeroing made it more managable. |
… enabled (#24108) refs #24094, soft reverts #23787 #23787 turned out to cause issues as described in #24094, but the changes are still positive, so it is now only enabled if compiling with `-d:nimOptIters`. Unfortunately the changes are really interwoven with each other so the checks for this switch in the code are a bit messy, but searching for `nimOptIters` should give the necessary clues to remove the switch properly later on. Locally tested that nimlangserver works but others can also check.
The issue is in copy codegen that violates memory, which was present before #23787, but was revealed likely because the memory layout changed. proc foo() =
let x = 123
iterator bar2(): int {.closure.} =
yield x
proc bar() =
let z = bar2
for y in z(): # just doing bar2() gives param not in env: x
echo y
bar()
foo() with gcc, I'm getting codegen error:
Take a careful look at this line: eqcopy___test50_u113(&(*colonenv_).colonup_, colonenv_); It tries to copy colonenv_ into a field of itself, which is obviously wrong. Unfortunately I'm not quite familiar with this logic, can anyone provide any input? |
It's not "obviously wrong", closure environments can be self-referencing which is why you need a cycle collector for them. This is even more true for the so called "up" pointers that are so complex that I keep forgetting how they work. |
Not pretending to understand, but my thinking was that "ups" always point to the parent closure env and "ups" can never be cyclic. Sure, cycles can form, just not through "ups". Am I wrong here? Also the pointer type mismatch kinda hints that this particular line is fishy at least? |
Sure, yes. |
-d:nimOptIter
is defined
Langserver seems to have circumvented the original issue in the master branch. Unfortunately, for the commit nim-lang/langserver@8839357 which I was testing on, #24316 does not fix it in my reproduction, the minimizations above were probably not correct. Running It crashes right before this call which was removed in this commit. The full log from langserver in VS Code (before restarts) is:
It seems like neither thread created above it actually starts, and not creating the threads does not cause the issue. Just creating a thread that takes a |
Ok, finally managed to reproduce, thanks @metagn. Now, TLDR. This issue should be fixed not by reverting my pr, but in any other suitable way!)) Long description:
The statements above can be easily backed by one of the following experiments:
Finally I suggest closing this issue for the reason of misused threading api. |
Sounds reasonable, in the worst case maybe a changelog entry for the new behavior and disclaimer.
It uses a potentially escaping address for this. If we don't change this it should at least still be documented in We can track this in this issue too since this is the root problem and the iterator changes were only tangential, but closing it is fine too. |
…24316) The first commit reverts the revert of #23787. The second fixes lambdalifting in convolutedly nested closures/closureiters. This is considered to be the reason of #24094, though I can't tell for sure, as I was not able to reproduce #24094 for complicated but irrelevant reasons. Therefore I ask @jmgomez, @metagn or anyone who could reproduce it to try it again with this PR. I would suggest this PR to not be squashed if possible, as the history is already messy enough. Some theory behind the lambdalifting fix: - A closureiter that captures anything outside its body will always have `:up` in its env. This property is now used as a trigger to lift any proc that captures such a closureiter. - Instantiating a closureiter involves filling out its `:up`, which was previously done incorrectly. The fixed algorithm is to use "current" env if it is the owner of the iter declaration, or traverse through `:up`s of env param until the common ancestor is found. --------- Co-authored-by: Andreas Rumpf <[email protected]>
Description
Download and build latest https://github.com/nim-lang/langserver
Remove the lock file and the requires from the
nimlangserver.nimble
so it uses the latest Nim to build.Run
nimble build
Open a nim project with the vscode extension (make sure the built
nimlangserver
is the one used)It will crash with the following (you can see the output in the
Nim Language Server
tab orNim Lsp
if you are running a newer version)Works fine with
2.0.8
and with2.0.9
Nim Version
Current Output
No response
Expected Output
No response
Known Workarounds
No response
Additional Information
No response
The text was updated successfully, but these errors were encountered: