When I use the following script:
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)}
I'm getting an error message: lua entry thread aborted: runtime error: attempt to yield across C-call boundary
.
I'm using the newest luasocket
installed from luarocks
with Lua 5.1 using nginx compiled with LuaJIT 2.1. What is causing this error message and how do I fix it?
smtp.send
uses LuaSocket's socket.protect
function for handling internal errors. This function is implemented in C and doesn't allow yielding in the current releases (the version in git HEAD now allows yielding on Lua 5.2+, see discussion 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
that should allow yielding on all Lua versions (at the cost of an extra temporary coroutine). You can try replacing the C function with that Lua function like so:
local socket = require("socket")
local base = _G
-- paste modified socket.protect function here
-- continue with your own code:
local smtp = require("socket.smtp")
-- ...
This is caused by the combined use of LuaJIT and socket.smtp, which spins up a coroutine. From 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.
It looks like the best workaround may be to use this implementation of require.lua: https://github.com/pygy/require.lua. It's written in pure Lua, instead of C, to get around this problem with LuaJIT.
I've seen this message in a somewhat similar situation; in my case it was related to the design of ngx_lua, which implements its own coroutine scheduler. This means that sock:receive
doesn't block, but instead does implicit yield
to the scheduler and, as the result, if the call to sock:receive
is made with a C function being on the stack, you are likely to get the error you see.
In my case I was making sock:receive
call from a debug hook and was getting this error until I switched to using socket methods from my own version of luasocket that doesn't yield. I'd check if socket.smtp
is using the "normal" version of luasocket.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With