Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
devel:languages:lua
lua-luv
luv-fix-segfault-from-gc.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File luv-fix-segfault-from-gc.patch of Package lua-luv
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)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor