From c0ac37c79f3d9fbc12b99541f58caaca8667182c Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 15 Apr 2025 12:00:23 +0200 Subject: Fix some tests (kinda) * split tasking_cancelling in two * add a timer in basic and tasking_cancelling as a temporary workaround for a deadlock in mingw ucrt64 builds --- unit_tests/scripts/lane/tasking_cancelling.lua | 89 ++++++---------------- .../scripts/lane/tasking_cancelling_with_hook.lua | 68 +++++++++++++++++ 2 files changed, 90 insertions(+), 67 deletions(-) create mode 100644 unit_tests/scripts/lane/tasking_cancelling_with_hook.lua (limited to 'unit_tests/scripts') diff --git a/unit_tests/scripts/lane/tasking_cancelling.lua b/unit_tests/scripts/lane/tasking_cancelling.lua index 85600ab..8bee3a6 100644 --- a/unit_tests/scripts/lane/tasking_cancelling.lua +++ b/unit_tests/scripts/lane/tasking_cancelling.lua @@ -15,69 +15,12 @@ local lanes_linda = assert(lanes.linda) -- ################################################################################################## -- ################################################################################################## -local function task(a, b, c) - lane_threadname("task("..a..","..b..","..c..")") - --error "111" -- testing error messages - assert(hey) - local v=0 - for i=a,b,c do - v= v+i - end - return v, hey -end - -local gc_cb = function(name_, status_) - PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'") -end - --- ################################################################################################## --- ################################################################################################## --- ################################################################################################## - -PRINT("\n\n", "---=== Tasking (cancelling) ===---", "\n\n") - -local task_launch2 = lanes_gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task) - -local N=999999999 -local lane9= task_launch2(1,N,1) -- huuuuuuge... - --- Wait until state changes "pending"->"running" --- -local st -local t0= os.time() -while os.time()-t0 < 5 do - st= lane9.status - io.stderr:write((i==1) and st.." " or '.') - if st~="pending" then break end -end -PRINT(" "..st) - -if st=="error" then - local _= lane9[0] -- propagate the error here -end -if st=="done" then - error("Looping to "..N.." was not long enough (cannot test cancellation)") -end -assert(st=="running", "st == " .. st) - --- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook -lane9:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count - -local t0= os.time() -while os.time()-t0 < 5 do - st= lane9.status - io.stderr:write((i==1) and st.." " or '.') - if st~="running" then break end -end -PRINT(" "..st) -assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") - -- cancellation of lanes waiting on a linda local limited = lanes_linda("limited") assert.fails(function() limited:limit("key", -1) end) assert.failsnot(function() limited:limit("key", 1) end) -- [[################################################ -limited:send("key", "hello") -- saturate linda +limited:send("key", "hello") -- saturate linda, so that subsequent sends will block for k, v in pairs(limited:dump()) do PRINT("limited[" .. tostring(k) .. "] = " .. tostring(v)) end @@ -88,11 +31,15 @@ local wait_send = function() end local wait_send_lane = lanes_gen("*", { name = 'auto' }, wait_send)() -repeat until wait_send_lane.status == "waiting" -print "wait_send_lane is waiting" +repeat + io.stderr:write('!') + -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) + lanes.sleep(0.1) +until wait_send_lane.status == "waiting" +PRINT "wait_send_lane is waiting" wait_send_lane:cancel() -- hard cancel, 0 timeout repeat until wait_send_lane.status == "cancelled" -print "wait_send_lane is cancelled" +PRINT "wait_send_lane is cancelled" --################################################]] local wait_receive = function() local k, v @@ -101,11 +48,15 @@ local wait_receive = function() end local wait_receive_lane = lanes_gen("*", { name = 'auto' }, wait_receive)() -repeat until wait_receive_lane.status == "waiting" -print "wait_receive_lane is waiting" +repeat + io.stderr:write('!') + -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) + lanes.sleep(0.1) +until wait_receive_lane.status == "waiting" +PRINT "wait_receive_lane is waiting" wait_receive_lane:cancel() -- hard cancel, 0 timeout repeat until wait_receive_lane.status == "cancelled" -print "wait_receive_lane is cancelled" +PRINT "wait_receive_lane is cancelled" --################################################]] local wait_receive_batched = function() local k, v1, v2 @@ -114,9 +65,13 @@ local wait_receive_batched = function() end local wait_receive_batched_lane = lanes_gen("*", { name = 'auto' }, wait_receive_batched)() -repeat until wait_receive_batched_lane.status == "waiting" -print "wait_receive_batched_lane is waiting" +repeat + io.stderr:write('!') + -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) + lanes.sleep(0.1) +until wait_receive_batched_lane.status == "waiting" +PRINT "wait_receive_batched_lane is waiting" wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout repeat until wait_receive_batched_lane.status == "cancelled" -print "wait_receive_batched_lane is cancelled" +PRINT "wait_receive_batched_lane is cancelled" --################################################]] diff --git a/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua new file mode 100644 index 0000000..56b934f --- /dev/null +++ b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua @@ -0,0 +1,68 @@ +local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() +print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) +local lanes = require_lanes_result_1 + +local require_assert_result_1, require_assert_result_2 = require "_assert" +print("require_assert_result:", require_assert_result_1, require_assert_result_2) + +local utils = lanes.require "_utils" +local PRINT = utils.MAKE_PRINT() + +-- ################################################################################################## +-- ################################################################################################## +-- ################################################################################################## + +local function task(a, b, c) + lane_threadname("task("..a..","..b..","..c..")") + --error "111" -- testing error messages + assert(hey) + local v=0 + for i=a,b,c do + v= v+i + end + return v, hey +end + +local gc_cb = function(name_, status_) + PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'") +end + +-- ################################################################################################## +-- ################################################################################################## +-- ################################################################################################## + +local generator = lanes.gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task) + +local N = 999999999 +local lane_h = generator(1,N,1) -- huuuuuuge... + +-- Wait until state changes "pending"->"running" +-- +local st +local t0 = os.time() +while os.time()-t0 < 5 do + st = lane_h.status + io.stderr:write((i==1) and st.." " or '.') + if st~="pending" then break end +end +PRINT(" "..st) + +if st == "error" then + local _ = lane_h[0] -- propagate the error here +end +if st == "done" then + error("Looping to "..N.." was not long enough (cannot test cancellation)") +end +assert(st == "running", "st == " .. st) + +-- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook +lane_h:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count + +local t0 = os.time() +while os.time()-t0 < 5 do + st = lane_h.status + io.stderr:write((i==1) and st.." " or '.') + if st~="running" then break end +end +PRINT(" "..st) +assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") -- cgit v1.2.3-55-g6feb