From 92944be3c3718095efa38e2a8db94844b1c7f739 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 28 May 2024 18:01:55 +0200 Subject: New Lanes finalizer API lanes.finally() --- tests/basic.lua | 6 ++--- tests/finalizer.lua | 70 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 46 insertions(+), 30 deletions(-) (limited to 'tests') diff --git a/tests/basic.lua b/tests/basic.lua index cfe6fd5..ab8a080 100644 --- a/tests/basic.lua +++ b/tests/basic.lua @@ -485,6 +485,6 @@ end local nameof_type, nameof_name = lanes.nameof(print) PRINT("name of " .. nameof_type .. " print = '" .. nameof_name .. "'") - --- -io.stderr:write "Done! :)\n" +-- install a finalizer that gets called upon Lanes's internal Universe is GCed. +-- that way, we print our message after anything that can be output by lanes that are still running at that point +lanes.finally(function() io.stderr:write "\n=======================================\nTEST OK\n" end) diff --git a/tests/finalizer.lua b/tests/finalizer.lua index 060e0a6..2acc39d 100644 --- a/tests/finalizer.lua +++ b/tests/finalizer.lua @@ -10,20 +10,22 @@ local lanes = require "lanes" lanes.configure{with_timers=false} +local finally = lanes.finally -local FN= "finalizer-test.tmp" +local FN = "finalizer-test.tmp" local cleanup -local which= os.time() % 2 -- 0/1 - -local function lane() - +local function lane(error_) set_finalizer(cleanup) - local f,err= io.open(FN,"w") + local st,err = pcall(finally, cleanup) -- should cause an error because called from a lane + assert(not st, "finally() should have thrown an error") + io.stderr:write("finally() raised error '", err, "'\n") + + local f,err = io.open(FN,"w") if not f then - error( "Could not create "..FN..": "..err ) + error( "Could not create "..FN..": "..err) end f:write( "Test file that should get removed." ) @@ -32,11 +34,10 @@ local function lane() -- don't forget to close the file immediately, else we won't be able to delete it until f is collected f:close() - if which==0 then - print "you loose" - error("aa") -- exception here; the value needs NOT be a string + if error_ then + io.stderr:write("Raising ", tostring(error_), "\n") + error(error_, 0) -- exception here; the value needs NOT be a string end - -- no exception end @@ -44,8 +45,8 @@ end -- This is called at the end of the lane; whether succesful or not. -- Gets the 'error()' parameter as parameter ('nil' if normal return). -- -cleanup= function(err) - +cleanup = function(err) + io.stderr:write "------------------------ In Worker Finalizer -----------------------\n" -- An error in finalizer will override an error (or success) in the main -- chunk. -- @@ -57,30 +58,45 @@ cleanup= function(err) io.stderr:write( "Cleanup after normal return\n" ) end - local _,err2= os.remove(FN) - print( "file removal result: ", tostring( err2)) + local _,err2 = os.remove(FN) + io.stderr:write( "file removal result: ", tostring(err2), "\n") assert(not err2) -- if this fails, it will be shown in the calling script -- as an error from the lane itself io.stderr:write( "Removed file "..FN.."\n" ) end -local lgen = lanes.gen("*", lane) +-- we need error_trace_level above "minimal" to get a stack trace out of h:join() +local lgen = lanes.gen("*", {error_trace_level = "basic"}, lane) + +local do_test = function(error_) -io.stderr:write "Launching the lane!\n" + io.stderr:write "======================== Launching the lane! =======================\n" -local h= lgen() + local h = lgen(error_) -local _,err,stack= h:join() -- wait for the lane (no automatic error propagation) -if err then - assert(stack) - io.stderr:write( "Lane error: "..tostring(err).."\n" ) - io.stderr:write( "\t", table.concat(stack,"\t\n"), "\n" ) + local _,err,stack = h:join() -- wait for the lane (no automatic error propagation) + if err then + assert(stack, "no stack trace on error, check 'error_trace_level'") + io.stderr:write( "Lane error: "..tostring(err).."\n" ) + io.stderr:write( "\t", table.concat(stack,"\t\n"), "\n" ) + end end -local f= io.open(FN,"r") -if f then - error( "CLEANUP DID NOT WORK: "..FN.." still exists!" ) +do_test(nil) +do_test("An error") + +local on_exit = function() + finally(nil) + io.stderr:write "=========================In Lanes Finalizer! =======================\n" + local f = io.open(FN,"r") + if f then + error( "CLEANUP DID NOT WORK: "..FN.." still exists!" ) + else + io.stderr:write(FN .. " was successfully removed\n") + end + io.stderr:write "Finished!\n" end -io.stderr:write "Finished!\n" +-- this function is called after script exit, when the state is closed +lanes.finally(on_exit) -- cgit v1.2.3-55-g6feb