当我使用以下脚本时:
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
。
我使用从luasocket
安装的最新luarocks
和使用LuaJIT 2.1编译的nginx的Lua 5.1。导致此错误消息的原因是什么?如何解决?
答案 0 :(得分:4)
这是由LuaJIT和socket.smtp的组合使用引起的,它们会旋转一个协同程序。来自https://github.com/openresty/lua-nginx-module/issues/376:
@AterCattus这是LuaJIT(和标准Lua)中的一个已知限制 5.1解释器)require()内置目前实现为C 内置,你不能发起收益。
看起来最好的解决方法可能是使用require.lua的这个实现:https://github.com/pygy/require.lua。它是用纯Lua而不是C编写的,用LuaJIT来解决这个问题。
答案 1 :(得分:4)
smtp.send
使用LuaSocket的socket.protect
函数来处理内部错误。此函数在C中实现,并且不允许在当前版本中产生(git HEAD中的版本现在允许在Lua 5.2+上产生,请参阅讨论here)。显然有人试图从内部屈服。在LuaSocket包中的etc/dispatch.lua
(更好地使用git HEAD版本)中,有一个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")
-- ...
答案 2 :(得分:2)
我在某种类似的情况下看到了这个消息;在我的例子中,它与ngx_lua的设计有关,它实现了自己的协同调度程序。这意味着sock:receive
不会阻塞,而是对调度程序执行隐式yield
,结果,如果对sock:receive
的调用是在C函数打开的情况下进行的堆栈,你可能会得到你看到的错误。
在我的情况下,我正在从调试钩子进行sock:receive
调用,并且在我切换到使用我自己的luasocket版本的套接字方法之前得到了这个错误。我要检查socket.smtp
是否正在使用"正常" luasocket的版本。