-
Notifications
You must be signed in to change notification settings - Fork 60
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
neovim crashes with "E41: Out of memory!" #1539
Comments
Related notes on the issue with building it as a shared library:
These relocations are ostensibly all of type R_AMD64_PC32:
Of note,
comes from
The special assembler is invoked thus:
It produces assembly files that it then gives to GCC; e.g., for the function shown above:
It's conceivable that the generated assembly is not quite right. More study required to determine where the bug is, exactly. |
@pfmooney and I have seen random crashes from Neovim 0.10 lately, and I have finally had some cycles to dig in and debug it. The crux of the issue is that the embedded LuaJIT library is doing some relatively daft things with mappings, and depending on how unlucky you get with random numbers, it will collide with the process heap and malloc() will stop being able to allocate more memory.
When this happens, the process exits unceremoniously with somewhat corrupted output:
I used DTrace to get a sense of what was causing the allocation failures. They're all failures from malloc(), and if you look at a regular nvim process that has not yet failed, it's not hard to see why:
Critically, in this particular instance, the heap currently extends up to
0x1205BF0
, and theMAP_ANON
mappings that LuaJIT has created are as low as0xB3C0000
, which is only 161MB away! The initial address that's chosen for the mapping is made up by a random number generator in LuaJIT, and constrained to be within about 2GB of some of the language runtime functions; these are compiled into the binary, so they're down under the heap in the address space. Further compounding the issue, LuaJIT appears to really want to grow its allocation downward, setting it on a collision course with the heap.This doesn't happen as much on, say, Ubuntu, because they are able to build and ship LuaJIT as a shared library. This library ends up loaded way up high in the address space, very far from the heap, and so mappings in that 2GB neighbourhood are less of an issue. We should try to do the same thing, but I believe some investigation may be required to make that work correctly.
In the meantime, it seems possible to work around the issue by preloading libumem and setting UMEM_OPTIONS to backend=mmap in the environment. This causes malloc() to be provided by umem, and to avoid the classic sbrk()-based heap entirely. We can provide a default value for UMEM_OPTIONS by adding a C function with the appropriate name to the resultant binary; e.g.,
Note that this is not a fix, and we should still also investigate building LuaJIT as a shared library, to at least be on the same footing as other common platforms that ship Neovim and LuaJIT.
The text was updated successfully, but these errors were encountered: