aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/executor.c
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2021-03-27 10:30:15 +0100
committerBjörn Linse <bjorn.linse@gmail.com>2021-04-03 16:27:58 +0200
commit5ed383057b5272d3777d2179128f474cc31317ea (patch)
tree46d8f18a6a7369c30ba86be0e03616b2d56e4a81 /src/nvim/lua/executor.c
parentabdda664108646a8f1bd3112abb8083d721d38e6 (diff)
downloadrneovim-5ed383057b5272d3777d2179128f474cc31317ea.tar.gz
rneovim-5ed383057b5272d3777d2179128f474cc31317ea.tar.bz2
rneovim-5ed383057b5272d3777d2179128f474cc31317ea.zip
lua: track reference ownership with ASAN when present
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r--src/nvim/lua/executor.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 03d178467b..d4c6e8e02e 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -5,6 +5,7 @@
#include <lualib.h>
#include <lauxlib.h>
+#include "nvim/assert.h"
#include "nvim/version.h"
#include "nvim/misc1.h"
#include "nvim/getchar.h"
@@ -18,6 +19,7 @@
#include "nvim/vim.h"
#include "nvim/ex_getln.h"
#include "nvim/ex_cmds2.h"
+#include "nvim/map.h"
#include "nvim/message.h"
#include "nvim/memline.h"
#include "nvim/buffer_defs.h"
@@ -63,6 +65,11 @@ typedef struct {
} \
}
+#if __has_feature(address_sanitizer)
+ PMap(handle_T) *nlua_ref_markers;
+# define NLUA_TRACK_REFS
+#endif
+
/// Convert lua error into a Vim error message
///
/// @param lstate Lua interpreter state.
@@ -547,6 +554,10 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
static lua_State *nlua_init(void)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
+#ifdef NLUA_TRACK_REFS
+ nlua_ref_markers = pmap_new(handle_T)();
+#endif
+
lua_State *lstate = luaL_newstate();
if (lstate == NULL) {
EMSG(_("E970: Failed to initialize lua interpreter"));
@@ -554,9 +565,13 @@ static lua_State *nlua_init(void)
}
luaL_openlibs(lstate);
nlua_state_init(lstate);
+
return lstate;
}
+// only to be used by nlua_enter and nlua_free_all_mem!
+static lua_State *global_lstate = NULL;
+
/// Enter lua interpreter
///
/// Calls nlua_init() if needed. Is responsible for pre-lua call initalization
@@ -567,26 +582,31 @@ static lua_State *nlua_init(void)
static lua_State *nlua_enter(void)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT
{
- static lua_State *global_lstate = NULL;
if (global_lstate == NULL) {
global_lstate = nlua_init();
}
lua_State *const lstate = global_lstate;
- // Last used p_rtp value. Must not be dereferenced because value pointed to
- // may already be freed. Used to check whether &runtimepath option value
- // changed.
- static const void *last_p_rtp = NULL;
- if (last_p_rtp != (const void *)p_rtp) {
- // stack: (empty)
- lua_getglobal(lstate, "vim");
- // stack: vim
- lua_pop(lstate, 1);
- // stack: (empty)
- last_p_rtp = (const void *)p_rtp;
- }
return lstate;
}
+void nlua_free_all_mem(void)
+{
+ if (!global_lstate) {
+ return;
+ }
+
+#ifdef NLUA_TRACK_REFS
+ if (nlua_refcount) {
+ fprintf(stderr, "%d lua references were leaked!", nlua_refcount);
+ }
+
+ pmap_free(handle_T)(nlua_ref_markers);
+#endif
+
+ nlua_refcount = 0;
+ lua_close(global_lstate);
+}
+
static void nlua_print_event(void **argv)
{
char *str = argv[0];
@@ -866,17 +886,31 @@ static int nlua_getenv(lua_State *lstate)
}
#endif
+
/// add the value to the registry
LuaRef nlua_ref(lua_State *lstate, int index)
{
lua_pushvalue(lstate, index);
- return luaL_ref(lstate, LUA_REGISTRYINDEX);
+ LuaRef ref = luaL_ref(lstate, LUA_REGISTRYINDEX);
+ if (ref > 0) {
+ // TODO: store traceback when LeakSanitizer is enabled
+ nlua_refcount++;
+#ifdef NLUA_TRACK_REFS
+ pmap_put(handle_T)(nlua_ref_markers, ref, xmalloc(3));
+#endif
+ }
+ return ref;
}
/// remove the value from the registry
void nlua_unref(lua_State *lstate, LuaRef ref)
{
if (ref > 0) {
+ nlua_refcount--;
+#ifdef NLUA_TRACK_REFS
+ // NB: don't remove entry from map to track double-unreff
+ xfree(pmap_get(handle_T)(nlua_ref_markers, ref));
+#endif
luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
}
}