Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Luasocket + nginx error - lua entry thread aborted: runtime error: attempt to yield across C-call boundary

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?

like image 421
iRyanBell Avatar asked May 07 '15 21:05

iRyanBell


3 Answers

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")
-- ...
like image 181
siffiejoe Avatar answered Sep 21 '22 19:09

siffiejoe


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.

like image 39
Mike Andrews Avatar answered Sep 21 '22 19:09

Mike Andrews


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.

like image 32
Paul Kulchenko Avatar answered Sep 21 '22 19:09

Paul Kulchenko