forked from pool/lua-luv
Updated to version 1.45 Also fixed segfault with weird lua-gc issue OBS-URL: https://build.opensuse.org/request/show/1130698 OBS-URL: https://build.opensuse.org/package/show/devel:languages:lua/lua-luv?expand=0&rev=42
93 lines
2.8 KiB
Diff
93 lines
2.8 KiB
Diff
diff --git a/src/handle.c b/src/handle.c
|
|
index 9180da34..0977a565 100644
|
|
--- a/src/handle.c
|
|
+++ b/src/handle.c
|
|
@@ -88,13 +88,19 @@ static int luv_is_closing(lua_State* L) {
|
|
return 1;
|
|
}
|
|
|
|
+static void luv_handle_free(uv_handle_t* handle);
|
|
+
|
|
static void luv_close_cb(uv_handle_t* handle) {
|
|
lua_State* L;
|
|
luv_handle_t* data = (luv_handle_t*)handle->data;
|
|
if (!data) return;
|
|
L = data->ctx->L;
|
|
- luv_call_callback(L, data, LUV_CLOSED, 0);
|
|
- luv_unref_handle(L, data);
|
|
+ if(data->ref > 0) {
|
|
+ luv_call_callback(L, data, LUV_CLOSED, 0);
|
|
+ luv_unref_handle(L, data);
|
|
+ } else {
|
|
+ luv_handle_free(handle);
|
|
+ }
|
|
}
|
|
|
|
static int luv_close(lua_State* L) {
|
|
@@ -127,12 +133,13 @@ static void luv_gc_cb(uv_handle_t* handle) {
|
|
static int luv_handle_gc(lua_State* L) {
|
|
uv_handle_t** udata = (uv_handle_t**)lua_touserdata(L, 1);
|
|
uv_handle_t* handle = *udata;
|
|
+ luv_handle_t* data = (luv_handle_t*)handle->data;
|
|
|
|
// Only cleanup if the handle hasn't been cleaned up yet.
|
|
- if (handle) {
|
|
+ if (data->ref == LUA_NOREF) {
|
|
if (!uv_is_closing(handle)) {
|
|
// If the handle is not closed yet, close it first before freeing memory.
|
|
- uv_close(handle, luv_gc_cb);
|
|
+ uv_close(handle, luv_handle_free);
|
|
}
|
|
else {
|
|
// Otherwise, free the memory right away.
|
|
@@ -140,6 +147,10 @@ static int luv_handle_gc(lua_State* L) {
|
|
}
|
|
// Mark as cleaned up by wiping the dangling pointer.
|
|
*udata = NULL;
|
|
+ } else {
|
|
+ // os.exit maybe cause gc before close_cb
|
|
+ // use LUA_REFNIL to tell close_cb to free memory.
|
|
+ data->ref = LUA_REFNIL;
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/src/lhandle.c b/src/lhandle.c
|
|
index 92b725a9..1c4cc800 100644
|
|
--- a/src/lhandle.c
|
|
+++ b/src/lhandle.c
|
|
@@ -104,6 +104,7 @@ static void luv_call_callback(lua_State* L, luv_handle_t* data, luv_callback_id
|
|
|
|
static void luv_unref_handle(lua_State* L, luv_handle_t* data) {
|
|
luaL_unref(L, LUA_REGISTRYINDEX, data->ref);
|
|
+ data->ref = LUA_NOREF;
|
|
luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[0]);
|
|
luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[1]);
|
|
}
|
|
diff --git a/src/fs.c b/src/fs.c
|
|
index 8ef36145..af59caa9 100644
|
|
--- a/src/fs.c
|
|
+++ b/src/fs.c
|
|
@@ -363,6 +363,9 @@ static int push_fs_result(lua_State* L, uv_fs_t* req) {
|
|
return 1;
|
|
}
|
|
case UV_FS_READDIR: {
|
|
+ luaL_unref(L, LUA_REGISTRYINDEX, data->data_ref);
|
|
+ data->data_ref = LUA_NOREF;
|
|
+
|
|
if(req->result > 0) {
|
|
size_t i;
|
|
uv_dir_t *dir = (uv_dir_t*)req->ptr;
|
|
@@ -938,6 +941,11 @@ static int luv_fs_readdir(lua_State* L) {
|
|
|
|
req = (uv_fs_t*)lua_newuserdata(L, uv_req_size(UV_FS));
|
|
req->data = luv_setup_req(L, ctx, ref);
|
|
+
|
|
+ // ref the luv_dir_t so it doesn't get garbage collected before the readdir cb
|
|
+ lua_pushvalue(L, 1);
|
|
+ ((luv_req_t*)req->data)->data_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
+
|
|
FS_CALL(uv_fs_readdir, req, dir->handle);
|
|
}
|
|
|
|
p(stat)
|