lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


As already discussed, Lua 5.4 is using a "non stackless" implementation.
That means that it uses the C stack for recursion in Lua functions.
Because of that, the maximum depth of recursion is much lower in 5.4
than it was in 5.3. In Linux, that limit could be around 20000 calls,
which seems more than enough. On other systems, however (e.g., Windows),
that limit must be much lower.

I am attaching here a test file that should check whether the limit
is good enough for your machine. The output should be something like
this:

    $ lua cstack.lua 
    testing C-stack overflow detection
    testing simple recursion:
    2164    	final count: 	2165
    testing stack overflow in message handling
    2413    	final count: 	2414
    testing recursion inside pattern matching
    testing stack-overflow in recursive 'gsub'
    181     	final count: 	181
    testing stack-overflow in recursive 'gsub' with metatables
    272     	final count: 	272
    OK

Or this if the limit is too high for the machine's stack:

    $ ulimit -S -s 400; lua cstack.lua 
    testing C-stack overflow detection
    testing simple recursion:
    1758    Segmentation fault (core dumped)

(The '1758' is how many recursions it did before crashing.)

In our tests, the current limit of 2200 was about right for
Windows 7/VS 2010. For Linux/gcc, it works with a limit of 30000.

If you could run this test in your machine, that would be helpful.
It would be even more helpful if you could play with the
constant LUAI_MAXCSTACK and find its maximum value that the
test does not crash. (You can change LUAI_MAXCSTACK in luaconf.h
or define it with a compiler option.)

Many thanks,

-- Roberto
-- $Id: testes/cstack.lua $
-- See Copyright Notice in file all.lua

print"testing C-stack overflow detection"

-- Segmentation faults in these tests probably result from a C-stack
-- overflow. To avoid these errors, recompile Lua with a smaller
-- value for the constant 'LUAI_MAXCCALLS' or else ensure a larger
-- stack for the program.

local function checkerror (msg, f, ...)
  local s, err = pcall(f, ...)
  assert(not s and string.find(err, msg))
end

local count
local back = string.rep("\b", 8)
local function progress ()
  count = count + 1
  local n = string.format("%-8d", count)
  io.stderr:write(back, n)
end


do    print("testing simple recursion:")
  count = 0
  local function foo ()
    progress()
    foo()
  end
  checkerror("stack overflow", foo)
  print("\tfinal count: ", count)
end


do  print("testing stack overflow in message handling")
  count = 0
  local function loop (x, y, z)
    progress()
    return 1 + loop(x, y, z)
  end
  local res, msg = xpcall(loop, loop)
  assert(msg == "error in error handling")
  print("\tfinal count: ", count)
end


-- bug since 2.5 (C-stack overflow in recursion inside pattern matching)
do  print("testing recursion inside pattern matching")
  local function f (size)
    local s = string.rep("a", size)
    local p = string.rep(".?", size)
    return string.match(s, p)
  end
  local m = f(80)
  assert(#m == 80)
  checkerror("too complex", f, 200000)
end


do  print("testing stack-overflow in recursive 'gsub'")
  count = 0
  local function foo ()
    progress()
    string.gsub("a", ".", foo)
  end
  checkerror("stack overflow", foo)
  print("\tfinal count: ", count)

  print("testing stack-overflow in recursive 'gsub' with metatables")
  count = 0
  local t = setmetatable({}, {__index = foo})
  foo = function ()
    count = count + 1
    progress(count)
    string.gsub("a", ".", t)
  end
  checkerror("stack overflow", foo)
  print("\tfinal count: ", count)
end

print'OK'