From 2af42c395c5a748b0bef9d0d59cff2a7ba8a9776 Mon Sep 17 00:00:00 2001 From: George Zhao Date: Fri, 26 May 2023 22:42:29 +0800 Subject: [PATCH] Check handle to close in current loop when `loop_gc` * Fix https://github.com/luvit/luv/issues/437 * Fix https://github.com/luvit/luv/issues/599 --- src/luv.c | 6 +++--- tests/manual-test-exit.lua | 22 ++++++++++++++++++++++ tests/manual-test-without-uv.run.lua | 4 ++++ tests/test-loop.lua | 28 ++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/manual-test-exit.lua create mode 100644 tests/manual-test-without-uv.run.lua diff --git a/src/luv.c b/src/luv.c index ad596faf..9dc603fd 100644 --- a/src/luv.c +++ b/src/luv.c @@ -794,8 +794,8 @@ LUALIB_API void luv_set_cthread(lua_State* L, luv_CFcpcall cpcall) { static void walk_cb(uv_handle_t *handle, void *arg) { - (void)arg; - if (!uv_is_closing(handle)) { + uv_loop_t* loop = arg; + if (handle->loop ==loop && !uv_is_closing(handle)) { uv_close(handle, luv_close_cb); } } @@ -806,7 +806,7 @@ static int loop_gc(lua_State *L) { if (loop==NULL) return 0; // Call uv_close on every active handle - uv_walk(loop, walk_cb, NULL); + uv_walk(loop, walk_cb, loop); // Run the event loop until all handles are successfully closed while (uv_loop_close(loop)) { uv_run(loop, UV_RUN_DEFAULT); diff --git a/tests/manual-test-exit.lua b/tests/manual-test-exit.lua new file mode 100644 index 00000000..39db7e6d --- /dev/null +++ b/tests/manual-test-exit.lua @@ -0,0 +1,22 @@ +--come from https://github.com/luvit/luv/issues/599 + +-- run `lua manual-test-exit.lua || echo $?` +-- it shoud print `5` + +local uv = require('luv') + +local function setTimeout(callback, ms) + local timer = uv.new_timer() + timer:start(ms, 0, function() + timer:stop() + timer:close() + callback() + end) + return timer +end + +setTimeout(function() + os.exit(5, true) +end, 1000) + +uv.run() diff --git a/tests/manual-test-without-uv.run.lua b/tests/manual-test-without-uv.run.lua new file mode 100644 index 00000000..c205888d --- /dev/null +++ b/tests/manual-test-without-uv.run.lua @@ -0,0 +1,4 @@ +local uv = require('luv') + +local test = uv.new_pipe(false) +uv.close(test) diff --git a/tests/test-loop.lua b/tests/test-loop.lua index f0a4504c..6f627a2c 100644 --- a/tests/test-loop.lua +++ b/tests/test-loop.lua @@ -10,4 +10,32 @@ return require('lib/tap')(function (test) end)) end) + test("issue #437, crash without uv.run", function (print, p, expect, uv) + local handle + handle = uv.spawn(arg[-1], { + args = { "tests/manual-test-without-uv.run.lua" } + }, + expect(function(status, signal) + -- macos status==0 + -- linux status==1 + assert(status==0 or status==1) + assert(signal==0) + handle:close() + end)) + uv.run() + end) + + test("issue #599, crash during calling os.exit", function (print, p, expect, uv) + local handle + handle = uv.spawn(arg[-1], { + args = { "tests/manual-test-exit.lua" } + }, + expect(function(status, signal) + assert(status==5) + assert(signal==0) + handle:close() + end)) + uv.run() + end) + end)