2015-05-07 14 views
5

Quando uso il seguente script:Luasocket + nginx errore - Lua filo di entrata interrotta: errore di runtime: tentativo di produrre capi di C-call confine

local smtp = require("socket.smtp") 
local from = "[email protected]" 
local rcpt = "[email protected]" 
local msg = { 
    headers = { 
    to = rcpt, 
    subject = "Hi" 
    }, 
    body = "Hello" 
} 
smtp.send{from = from,rcpt = rcpt,source = smtp.message(msg)} 

Ricevo un messaggio di errore: lua entry thread aborted: runtime error: attempt to yield across C-call boundary.

Sto utilizzando il nuovo luasocket installato da luarocks con Lua 5.1 utilizzando nginx compilato con LuaJIT 2.1. Qual è la causa di questo messaggio di errore e come risolverlo?

+0

Hai un esempio completo che possiamo inserire in 'content_by_lua_file' per vedere dove fallisce? Fallisce sulla riga 'smtp.send' o' require'? Sospetto che sia il primo, ma vorrei confermare. –

+0

Questo è praticamente l'esempio completo. Fallisce sulla funzione di invio. – arby

risposta

4

smtp.send utilizza la funzione socket.protect di LuaSocket per la gestione degli errori interni. Questa funzione è implementata in C e non consente la resa nelle versioni correnti (la versione in git HEAD ora consente di ottenere risultati su Lua 5.2+, vedere la discussione here). Apparentemente qualcuno cerca di cedere dall'interno. In etc/dispatch.lua nel pacchetto LuaSocket (meglio usare la versione git HEAD) c'è uno replacement function for socket.protect che dovrebbe consentire di cedere su tutte le versioni di Lua (al costo di una coroutine extra temporanea). Puoi provare a sostituire la funzione C con quella funzione Lua in questo modo:

local socket = require("socket") 
local base = _G 
-- paste modified socket.protect function here 

-- continue with your own code: 
local smtp = require("socket.smtp") 
-- ... 
+0

"qualcuno cerca di cedere da dentro" è il nocciolo del problema. Se lo stesso script funziona da LuaJIT standalone usando il pacchetto luasocket, deve essere correlato a ngx_lua. Il problema nel mio caso era che veniva utilizzata la libreria socket ngx_lua (che implica la resa implicita) e la correzione consisteva nell'utilizzare la libreria luasocket di serie. –

+0

Eliminare il 'rendimento' risolverebbe anche il problema. Ma come lo fai? Il modulo socket.smtp tenta già di caricare le funzioni LuaSocket predefinite tramite 'require (" socket ")' - non conosce nemmeno le versioni di Nginx. Come si impedisce a Nginx di sostituire le funzioni interne di LuaSocket (apparentemente)? Anche se gestisci, le funzioni originali di LuaSocket stanno bloccando (il che probabilmente è il motivo per cui Nginx implementa in primo luogo il proprio scheduler basato su coroutine) ... – siffiejoe

2

Ho visto questo messaggio in una situazione piuttosto simile; nel mio caso era legato al design di ngx_lua, che implementa il proprio schedulatore di coroutine. Ciò significa che sock:receive non si blocca, ma invece esegue loimplicito nello scheduler e, di conseguenza, se la chiamata a sock:receive viene eseguita con una funzione C in pila, è probabile che si verifichi l'errore visualizzato.

Nel mio caso stavo effettuando la chiamata sock:receive da un hook di debug e ricevevo questo errore fino a quando non sono passato a utilizzare i metodi socket dalla mia versione di luasocket che non produce. Verificerei se socket.smtp utilizza la versione "normale" di luasocket.

4

Ciò è causato dall'uso combinato di LuaJIT e socket.smtp, che fa girare una coroutine. Da 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.

Sembra che la soluzione migliore potrebbe essere quella di utilizzare questa implementazione di require.lua: https://github.com/pygy/require.lua. È scritto in puro Lua, anziché in C, per ovviare a questo problema con LuaJIT.

+0

Hmm, ho scaricato 'require-lua 0.1.7-2' e installato tramite luarocks, quindi metto' require = require "require" .require' nella parte superiore del mio script. Sto ancora ricevendo lo stesso errore: 'tenta di cedere attraverso C-call boundary dalla funzione smtp.send. – arby

+0

arby, sembra che la risposta di @ siffiejoe sia corretta. Se socket.protect è scritto in C, questo è il vero problema di fondo! –