From b57574d6fb9071b2f8f261b32c9378ed72db7023 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 6 Jul 2020 12:09:44 -0300 Subject: Keep memory errors as memory errors Allow memory errors to be raised through the API (throwing the error with the memory error message); error in external allocations raises a memory error; memory errors in coroutines are re-raised as memory errors. --- testes/api.lua | 75 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 16 deletions(-) (limited to 'testes') diff --git a/testes/api.lua b/testes/api.lua index 9447e42a..95551481 100644 --- a/testes/api.lua +++ b/testes/api.lua @@ -11,6 +11,9 @@ local debug = require "debug" local pack = table.pack +-- standard error message for memory errors +local MEMERRMSG = "not enough memory" + function tcheck (t1, t2) assert(t1.n == (t2.n or #t2) + 1) for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end @@ -408,7 +411,7 @@ do -- memory error T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k) - assert(T.checkpanic("newuserdata 20000") == "not enough memory") + assert(T.checkpanic("newuserdata 20000") == MEMERRMSG) T.totalmem(0) -- restore high limit -- stack error @@ -1153,40 +1156,74 @@ do end -------------------------------------------------------------------------- --- testing memory limits -------------------------------------------------------------------------- +--[[ +** {================================================================== +** Testing memory limits +** =================================================================== +--]] + print("memory-allocation errors") checkerr("block too big", T.newuserdata, math.maxinteger) collectgarbage() local f = load"local a={}; for i=1,100000 do a[i]=i end" T.alloccount(10) -checkerr("not enough memory", f) +checkerr(MEMERRMSG, f) T.alloccount() -- remove limit + +-- test memory errors; increase limit for maximum memory by steps, +-- o that we get memory errors in all allocations of a given +-- task, until there is enough memory to complete the task without +-- errors. +function testbytes (s, f) + collectgarbage() + local M = T.totalmem() + local oldM = M + local a,b = nil + while true do + collectgarbage(); collectgarbage() + T.totalmem(M) + a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f) + T.totalmem(0) -- remove limit + if a and b == "OK" then break end -- stop when no more errors + if b ~= "OK" and b ~= MEMERRMSG then -- not a memory error? + error(a, 0) -- propagate it + end + M = M + 7 -- increase memory limit + end + print(string.format("minimum memory for %s: %d bytes", s, M - oldM)) + return a +end + -- test memory errors; increase limit for number of allocations one -- by one, so that we get memory errors in all allocations of a given -- task, until there is enough allocations to complete the task without -- errors. -function testamem (s, f) - collectgarbage(); collectgarbage() +function testalloc (s, f) + collectgarbage() local M = 0 local a,b = nil while true do + collectgarbage(); collectgarbage() T.alloccount(M) - a, b = pcall(f) + a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f) T.alloccount() -- remove limit - if a and b then break end -- stop when no more errors - if not a and not -- `real' error? - (string.find(b, "memory") or string.find(b, "overflow")) then - error(b, 0) -- propagate it + if a and b == "OK" then break end -- stop when no more errors + if b ~= "OK" and b ~= MEMERRMSG then -- not a memory error? + error(a, 0) -- propagate it end M = M + 1 -- increase allocation limit end - print(string.format("limit for %s: %d allocations", s, M)) - return b + print(string.format("minimum allocations for %s: %d allocations", s, M)) + return a +end + + +local function testamem (s, f) + testalloc(s, f) + return testbytes(s, f) end @@ -1196,8 +1233,11 @@ assert(b == 10) -- testing memory errors when creating a new state -b = testamem("state creation", T.newstate) -T.closestate(b); -- close new state +testamem("state creation", function () + local st = T.newstate() + if st then T.closestate(st) end -- close new state + return st +end) testamem("empty-table creation", function () return {} @@ -1345,6 +1385,9 @@ testamem("growing stack", function () return foo(100) end) +-- }================================================================== + + do -- testing failing in 'lua_checkstack' local res = T.testC([[rawcheckstack 500000; return 1]]) assert(res == false) -- cgit v1.2.3-55-g6feb