Luasocket + nginx error - lua entry thread aborted: runtime error: attempt to yield across C-call boundary
Luasocket + nginx error - lua entry thread aborted: runtime error: attempt to yield across C-call boundary
当我使用以下脚本时:
local smtp = require("socket.smtp")
local from = "from@host"
local rcpt = "rcpt@host"
local msg = {
headers = {
to = rcpt,
subject = "Hi"
},
body = "Hello"
}
smtp.send{from = from,rcpt = rcpt,source = smtp.message(msg)}
我收到一条错误消息:lua entry thread aborted: runtime error: attempt to yield across C-call boundary
。
我正在使用从 luarocks
安装的最新 luasocket
和 Lua 5.1,使用用 LuaJIT 2.1 编译的 nginx。是什么导致了此错误消息,我该如何解决?
我在类似的情况下看到过这条消息;在我的例子中,它与 ngx_lua 的设计有关,它实现了自己的协程调度程序。这意味着 sock:receive
不会阻塞,而是隐式 yield
到调度程序,因此,如果对 sock:receive
的调用是使用堆栈上的 C 函数进行的,您很可能会收到您看到的错误。
在我的例子中,我从调试挂钩进行 sock:receive
调用并收到此错误,直到我切换到使用我自己版本的 luasocket 中不产生的套接字方法。我会检查 socket.smtp
是否使用 "normal" 版本的 luasocket。
这是由于 LuaJIT 和 socket.smtp 的组合使用引起的,它启动了协程。来自 https://github.com/openresty/lua-nginx-module/issues/376:
@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.
看起来最好的解决方法可能是使用 require.lua 的这个实现:https://github.com/pygy/require.lua。它是用纯 Lua 而不是 C 编写的,以通过 LuaJIT 解决这个问题。
smtp.send
使用 LuaSocket 的 socket.protect
函数来处理内部错误。此函数在 C 中实现,并且在当前版本中不允许屈服(git HEAD 中的版本现在允许在 Lua 5.2+ 上屈服,请参阅应该允许屈服的讨论 here). Apparently someone tries to yield from within it. In etc/dispatch.lua
in the LuaSocket package (better use the git HEAD version) there is a replacement function for socket.protect
所有 Lua 版本(以额外的临时协程为代价)。您可以尝试用 Lua 函数替换 C 函数,如下所示:
local socket = require("socket")
local base = _G
-- paste modified socket.protect function here
-- continue with your own code:
local smtp = require("socket.smtp")
-- ...
当我使用以下脚本时:
local smtp = require("socket.smtp")
local from = "from@host"
local rcpt = "rcpt@host"
local msg = {
headers = {
to = rcpt,
subject = "Hi"
},
body = "Hello"
}
smtp.send{from = from,rcpt = rcpt,source = smtp.message(msg)}
我收到一条错误消息:lua entry thread aborted: runtime error: attempt to yield across C-call boundary
。
我正在使用从 luarocks
安装的最新 luasocket
和 Lua 5.1,使用用 LuaJIT 2.1 编译的 nginx。是什么导致了此错误消息,我该如何解决?
我在类似的情况下看到过这条消息;在我的例子中,它与 ngx_lua 的设计有关,它实现了自己的协程调度程序。这意味着 sock:receive
不会阻塞,而是隐式 yield
到调度程序,因此,如果对 sock:receive
的调用是使用堆栈上的 C 函数进行的,您很可能会收到您看到的错误。
在我的例子中,我从调试挂钩进行 sock:receive
调用并收到此错误,直到我切换到使用我自己版本的 luasocket 中不产生的套接字方法。我会检查 socket.smtp
是否使用 "normal" 版本的 luasocket。
这是由于 LuaJIT 和 socket.smtp 的组合使用引起的,它启动了协程。来自 https://github.com/openresty/lua-nginx-module/issues/376:
@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.
看起来最好的解决方法可能是使用 require.lua 的这个实现:https://github.com/pygy/require.lua。它是用纯 Lua 而不是 C 编写的,以通过 LuaJIT 解决这个问题。
smtp.send
使用 LuaSocket 的 socket.protect
函数来处理内部错误。此函数在 C 中实现,并且在当前版本中不允许屈服(git HEAD 中的版本现在允许在 Lua 5.2+ 上屈服,请参阅应该允许屈服的讨论 here). Apparently someone tries to yield from within it. In etc/dispatch.lua
in the LuaSocket package (better use the git HEAD version) there is a replacement function for socket.protect
所有 Lua 版本(以额外的临时协程为代价)。您可以尝试用 Lua 函数替换 C 函数,如下所示:
local socket = require("socket")
local base = _G
-- paste modified socket.protect function here
-- continue with your own code:
local smtp = require("socket.smtp")
-- ...