mirror of
https://github.com/neovim/neovim.git
synced 2026-08-26 00:51:53 +00:00
fix(lifecycle): Lua state not freed if free_all_mem() is re-entered #41366
Problem:
Leak reported by ASAN CI, always at Lua state init.
ERROR: LeakSanitizer: detected memory leaks
strbuf_init src/cjson/strbuf.c:62:22
json_create_config src/cjson/lua_cjson.c:635:5
lua_cjson_new src/cjson/lua_cjson.c:2060:5
nlua_state_add_stdlib src/nvim/lua/stdlib.c:840:3
nlua_state_init src/nvim/lua/executor.c:973:3
...
SUMMARY: AddressSanitizer: 1055 byte(s) leaked in 2 allocation(s).
Analysis:
`getout()` may run during `free_all_mem()` (that's why it checks
`!entered_free_all_mem`). If that happens, the second `os_exit()`
returns early from `free_all_mem()` then `exit()` is called and Lua
state is never closed.
Solution:
Always call `nlua_free_all_mem()` in the early-return case.
This commit is contained in:
@@ -1061,12 +1061,14 @@ static lua_State *nlua_init_state(bool thread)
|
||||
return lstate;
|
||||
}
|
||||
|
||||
/// Disposes global Lua state. Idempotent, harmless if called multiple times.
|
||||
void nlua_free_all_mem(void)
|
||||
{
|
||||
if (!global_lstate) {
|
||||
return;
|
||||
}
|
||||
lua_State *lstate = global_lstate;
|
||||
global_lstate = NULL;
|
||||
nlua_unref_global(lstate, require_ref);
|
||||
nlua_common_free_all_mem(lstate);
|
||||
nlua_treesitter_free();
|
||||
|
||||
@@ -861,9 +861,10 @@ void free_all_mem(void)
|
||||
{
|
||||
buf_T *buf, *nextbuf;
|
||||
|
||||
// When we cause a crash here it is caught and Vim tries to exit cleanly.
|
||||
// Don't try freeing everything again.
|
||||
// If a routine below recurses into free_all_mem, don't try freeing everything again.
|
||||
if (entered_free_all_mem) {
|
||||
// Except the Lua state. #39675
|
||||
nlua_free_all_mem();
|
||||
return;
|
||||
}
|
||||
entered_free_all_mem = true;
|
||||
|
||||
Reference in New Issue
Block a user