mirror of
https://github.com/neovim/neovim.git
synced 2026-08-27 09:31:47 +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;
|
return lstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disposes global Lua state. Idempotent, harmless if called multiple times.
|
||||||
void nlua_free_all_mem(void)
|
void nlua_free_all_mem(void)
|
||||||
{
|
{
|
||||||
if (!global_lstate) {
|
if (!global_lstate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lua_State *lstate = global_lstate;
|
lua_State *lstate = global_lstate;
|
||||||
|
global_lstate = NULL;
|
||||||
nlua_unref_global(lstate, require_ref);
|
nlua_unref_global(lstate, require_ref);
|
||||||
nlua_common_free_all_mem(lstate);
|
nlua_common_free_all_mem(lstate);
|
||||||
nlua_treesitter_free();
|
nlua_treesitter_free();
|
||||||
|
|||||||
@@ -861,9 +861,10 @@ void free_all_mem(void)
|
|||||||
{
|
{
|
||||||
buf_T *buf, *nextbuf;
|
buf_T *buf, *nextbuf;
|
||||||
|
|
||||||
// When we cause a crash here it is caught and Vim tries to exit cleanly.
|
// If a routine below recurses into free_all_mem, don't try freeing everything again.
|
||||||
// Don't try freeing everything again.
|
|
||||||
if (entered_free_all_mem) {
|
if (entered_free_all_mem) {
|
||||||
|
// Except the Lua state. #39675
|
||||||
|
nlua_free_all_mem();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entered_free_all_mem = true;
|
entered_free_all_mem = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user