content_by_lua+require+coroutine throws attempt to yield across C-call boundary
atercattus opened this issue · comments
Hello.
I have nginx 1.6.0 + luajit 2.0.2 with config:
# nginx.conf
lua_package_path '/path/to/lua/?.lua;;';
location / {
#content_by_lua_file '/path/to/lua/foo.lua'; # works fine
content_by_lua 'require("foo")'; # fail
}
# foo.lua
local function c()
return coroutine.wrap(function()
for i = 1, 10 do
coroutine.yield(i)
end
end)
end
for v in c() do
ngx.say(v)
end
An error occurs "lua entry thread aborted: runtime error: attempt to yield across C-call boundary".
@atercattus This is a known limitation in LuaJIT (and the standard Lua 5.1 interpreter) that the require() builtin is currently implemented as a C builtin across which you cannot initiate a yield. A work-around is to put your coroutine operations in a function in your Lua module and let the caller call your function explicitly after require(), for example,
local foo = require "foo"
foo.go()
or more concisely:
require("foo").go()
And your for v in c() do ... end
loop should be in the function named go
(or something else) in your foo.lua
file.
Mike Pall is going to reimplement the require
builtin with LuaJIT bytecode in LuaJIT and by that time this limitation will get removed. You can prod him on the luajit mailing list and/or sponsor him to work on it directly ;)
Sponsorship of development is a good option.
Thanks.
FWIW, https://github.com/pygy/require.lua implements require
in plain Lua, sidestepping the problem.
I'll test it more thoroughly tomorrow, but AFAICT, it works like the original.
You can sponsor me retroactively, if you want ;-)