Description
Did you check docs and existing issues?
- I have read all the lazy.nvim docs
- I have updated the plugin to the latest version before submitting this issue
- I have searched the existing issues of lazy.nvim
- I have searched the existing issues of plugins related to this issue
Neovim version (nvim -v)
v0.11.0-dev-1201+g0e2f92ed79
Operating system/version
Alpine Linux v3.14
Describe the bug
(Note: this reproduces on a wide variety of Neovim commits, and on later versions of Alpine and on Gentoo with a musl profile.)
lazy.nvim segfaults on i686-musl systems. It seems that this can be fixed with the following patch:
diff --git a/lua/lazy/stats.lua b/lua/lazy/stats.lua
index 015a2be..5195a56 100644
--- a/lua/lazy/stats.lua
+++ b/lua/lazy/stats.lua
@@ -34,51 +34,51 @@ end
function M.cputime()
if M.C == nil then
pcall(function()
ffi.cdef([[
typedef long time_t;
typedef int clockid_t;
typedef struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
} nanotime;
int clock_gettime(clockid_t clk_id, struct timespec *tp);
]])
M.C = ffi.C
end)
end
local function real()
local pnano = assert(ffi.new("nanotime[?]", 1))
local CLOCK_PROCESS_CPUTIME_ID = jit.os == "OSX" and 12 or 2
ffi.C.clock_gettime(CLOCK_PROCESS_CPUTIME_ID, pnano)
return tonumber(pnano[0].tv_sec) * 1e3 + tonumber(pnano[0].tv_nsec) / 1e6
end
local function fallback()
return (vim.uv.hrtime() - require("lazy")._start) / 1e6
end
- local ok, ret = pcall(real)
- if ok then
- M.cputime = real
- M._stats.real_cputime = true
- return ret
- else
+ -- local ok, ret = pcall(real)
+ -- if ok then
+ -- M.cputime = real
+ -- M._stats.real_cputime = true
+ -- return ret
+ -- else
M.cputime = fallback
return fallback()
- end
+ -- end
end
function M.stats()
M._stats.count = 0
M._stats.loaded = 0
for _, plugin in pairs(require("lazy.core.config").plugins) do
M._stats.count = M._stats.count + 1
if plugin._.loaded then
M._stats.loaded = M._stats.loaded + 1
end
end
return M._stats
end
return M
The typedef long time_t;
is certainly incorrect here -- long
is int32_t
on i686, but time_t
is int64_t
.
(This is insufficient to fix the segfault, but it's at least an easy thing to fix.)
FWIW, an example stack trace on segfault is:
#0 0x56a8e8fe in lj_alloc_free (msp=0xf7e98008, ptr=<optimized out>) at lj_alloc.c:1400
#1 0x56abb727 in lj_mem_free (osize=<optimized out>, p=0xf7de6940, g=0xf7e981f8)
at /code/.deps/build/src/luajit/src/lj_gc.h:122
#2 lj_cdata_free (g=0xf7e981f8, cd=<optimized out>) at lj_cdata.c:83
#3 0x56a97077 in gc_sweep (g=g@entry=0xf7e981f8, p=0xf7e92218, lim=9, lim@entry=40) at lj_gc.c:423
#4 0x56a97d6a in gc_onestep (L=0xf7e981c8) at lj_gc.c:683
#5 0x56a9840b in lj_gc_step (L=L@entry=0xf7e981c8) at lj_gc.c:732
#6 0x56a851d7 in lj_parse_keepstr (ls=ls@entry=0xffef0ca8, str=0xf7e9f2b1 "` changed `dir`:\n- from: `\"", len=26)
at lj_parse.c:246
#7 0x56a820bd in lex_string (tv=<optimized out>, ls=0xffef0ca8) at lj_lex.c:285
#8 lex_scan (ls=ls@entry=0xffef0ca8, tv=tv@entry=0xffef0cb0) at lj_lex.c:368
#9 0x56a82a05 in lj_lex_next (ls=ls@entry=0xffef0ca8) at lj_lex.c:460
#10 0x56a85806 in expr_binop (ls=ls@entry=0xffef0ca8, v=v@entry=0xffef02a8, limit=limit@entry=4) at lj_parse.c:2118
#11 0x56a85d7f in expr_binop (ls=ls@entry=0xffef0ca8, v=v@entry=0xffef0360, limit=limit@entry=0) at lj_parse.c:2121
#12 0x56a88678 in expr (v=0xffef0360, ls=0xffef0ca8) at lj_parse.c:2132
#13 expr_list (v=0xffef0360, ls=0xffef0ca8) at lj_parse.c:1899
#14 parse_local (ls=0xffef0ca8) at lj_parse.c:2284
#15 parse_stmt (ls=0xffef0ca8) at lj_parse.c:2676
#16 parse_chunk (ls=ls@entry=0xffef0ca8) at lj_parse.c:2713
#17 0x56a87b57 in parse_block (ls=0xffef0ca8) at lj_parse.c:2429
#18 parse_then (ls=0xffef0ca8) at lj_parse.c:2619
#19 parse_if (line=99, ls=0xffef0ca8) at lj_parse.c:2629
#20 parse_stmt (ls=0xffef0ca8) at lj_parse.c:2655
#21 parse_chunk (ls=ls@entry=0xffef0ca8) at lj_parse.c:2713
#22 0x56a87b57 in parse_block (ls=0xffef0ca8) at lj_parse.c:2429
#23 parse_then (ls=0xffef0ca8) at lj_parse.c:2619
#24 parse_if (line=95, ls=0xffef0ca8) at lj_parse.c:2629
#25 parse_stmt (ls=0xffef0ca8) at lj_parse.c:2655
#26 parse_chunk (ls=ls@entry=0xffef0ca8) at lj_parse.c:2713
#27 0x56a853a3 in parse_body (ls=ls@entry=0xffef0ca8, e=e@entry=0xffef08e0, needself=<optimized out>,
line=line@entry=71) at lj_parse.c:1876
#28 0x56a87713 in parse_func (line=71, ls=0xffef0ca8) at lj_parse.c:2309
#29 parse_stmt (ls=0xffef0ca8) at lj_parse.c:2672
#30 parse_chunk (ls=ls@entry=0xffef0ca8) at lj_parse.c:2713
#31 0x56a88aed in lj_parse (ls=ls@entry=0xffef0ca8) at lj_parse.c:2747
#32 0x56a88be4 in cpparser (L=0xf7e981c8, dummy=0x0, ud=0xffef0ca8) at lj_load.c:50
#33 0x56a9539c in lj_vm_cpcall ()
#34 0x56a88da7 in lua_loadx (L=L@entry=0xf7e981c8, reader=reader@entry=0x56a88c90 <reader_file>,
data=data@entry=0xffef0d6c,
chunkname=chunkname@entry=0xf7e28afc "@/root/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/meta.lua",
mode=mode@entry=0x0) at lj_load.c:72
#35 0x56a88ef2 in luaL_loadfilex (L=L@entry=0xf7e981c8,
filename=filename@entry=0xf7ddbf3c "/root/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/meta.lua",
mode=mode@entry=0x0) at lj_load.c:117
#36 0x56ac6877 in lj_cf_loadfile (L=0xf7e981c8) at lib_base.c:386
#37 0x56a95078 in lj_BC_FUNCC ()
#38 0x56acbfc4 in lj_cf_package_require (L=0xf7e981c8) at lib_package.c:453
#39 0x56a95078 in lj_BC_FUNCC ()
#40 0x56acc0b9 in lj_cf_package_require (L=0xf7e981c8) at lib_package.c:464
#41 0x56a95078 in lj_BC_FUNCC ()
#42 0x56acc0b9 in lj_cf_package_require (L=0xf7e981c8) at lib_package.c:464
#43 0x56a95078 in lj_BC_FUNCC ()
#44 0x56a80af4 in lua_pcall (L=0xf7e981c8, nargs=0, nresults=0, errfunc=-2) at lj_api.c:1151
#45 0x5683d2d5 in nlua_pcall (lstate=0xf7e981c8, nargs=0, nresults=0) at ../src/nvim/lua/executor.c:174
#46 0x56841700 in nlua_exec_file (path=0xf7e0a3a0 "/root/.config/nvim/init.lua") at ../src/nvim/lua/executor.c:1860
#47 0x56935789 in do_source (fname=0xf7e11cb0 "/root/.config/nvim/init.lua", check_other=1, is_vimrc=1, ret_sid=0x0)
at ../src/nvim/runtime.c:2224
#48 0x5684faad in do_user_initialization () at ../src/nvim/main.c:1995
#49 0x5684ffa5 in source_startup_scripts (parmp=0xffef1604) at ../src/nvim/main.c:2108
#50 0x5684c102 in main (argc=2, argv=0xffef1764) at ../src/nvim/main.c:463
How exactly we get to gc_sweep
differs, but the trace always ends in those same frames #0-#3
.
Steps To Reproduce
-
Be on an i686-musl platform. (The
muslcc/i686:i686-linux-musl
Docker container is sufficient.) -
Use the following
init.lua
:-- Bootstrap lazy.nvim local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" if not (vim.uv or vim.loop).fs_stat(lazypath) then local lazyrepo = "https://github.com/folke/lazy.nvim.git" local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) if vim.v.shell_error ~= 0 then vim.api.nvim_echo({ { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, { out, "WarningMsg" }, { "\nPress any key to exit..." }, }, true, {}) vim.fn.getchar() os.exit(1) end end vim.opt.rtp:prepend(lazypath) -- Make sure to setup `mapleader` and `maplocalleader` before -- loading lazy.nvim so that mappings are correct. -- This is also a good place to setup other settings (vim.opt) vim.g.mapleader = " " vim.g.maplocalleader = "\\" -- Setup lazy.nvim require("lazy").setup({ }) collectgarbage()
-
Open
nvim ~/.config/nvim/init.lua
(or another not-tiny file; if it doesn't repro, open another/larger file) -
Get a segfault
Expected Behavior
Don't segfault
Repro
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
-- add any other plugins here
},
})
-- not always necessary
collectgarbage()