2015-05-07 13 views
5

Khi tôi sử dụng kịch bản sau đây:Luasocket + nginx lỗi - lua nhập chủ đề hủy bỏ: lỗi runtime: nỗ lực để mang lại trên ranh giới C gọi

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)} 

tôi nhận được một thông báo lỗi: lua entry thread aborted: runtime error: attempt to yield across C-call boundary.

Tôi đang sử dụng luasocket mới nhất được cài đặt từ luarocks với Lua 5.1 bằng nginx được biên dịch bằng LuaJIT 2.1. Điều gì gây ra thông báo lỗi này và cách khắc phục sự cố này?

+0

Bạn có ví dụ đầy đủ chúng ta có thể cắm vào 'content_by_lua_file' để xem vị trí không thành công? Liệu nó có thất bại trên dòng 'smtp.send' hoặc' require' không? Tôi nghi ngờ đó là trước đây, nhưng muốn xác nhận. –

+0

Đó là khá nhiều ví dụ đầy đủ. Nó không thành công trên chức năng gửi. – arby

Trả lời

4

smtp.send sử dụng chức năng socket.protect của LuaSocket để xử lý lỗi nội bộ. Chức năng này được thực hiện trong C và không cho phép năng suất trong các bản phát hành hiện tại (phiên bản trong git HEAD bây giờ cho phép sinh lời trên Lua 5.2+, xem thảo luận here). Dường như ai đó cố gắng thu lợi từ bên trong nó. Trong etc/dispatch.lua trong gói LuaSocket (sử dụng tốt hơn phiên bản git HEAD) có một replacement function for socket.protect nên cho phép sinh lãi trên tất cả các phiên bản Lua (với chi phí của một coroutine phụ tạm thời). Bạn có thể thử thay thế hàm C bằng hàm Lua giống như vậy:

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

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

'ai đó cố gắng thu lợi từ bên trong nó' là mấu chốt của vấn đề. Nếu cùng một kịch bản hoạt động từ LuaJIT độc lập sử dụng gói luasocket, nó phải liên quan đến ngx_lua. Vấn đề trong trường hợp của tôi là thư viện socket ngx_lua đã được sử dụng (có hiệu suất ngầm) và sửa chữa là sử dụng thư viện luasocket cổ phiếu. –

+0

Loại bỏ 'yield' cũng sẽ giải quyết được vấn đề. Nhưng làm thế nào để bạn làm điều đó? Module socket.smtp đã cố tải các hàm LuaSocket mặc định thông qua 'require (" socket ")' - nó thậm chí không biết về các phiên bản Nginx. Làm thế nào để bạn ngăn Nginx thay thế các hàm bên trong của LuaSocket (rõ ràng)? Ngay cả khi bạn quản lý, các hàm LuaSocket ban đầu đang chặn (đó có lẽ là lý do tại sao Nginx thực hiện bộ lập lịch dựa trên coroutine của nó ngay từ đầu) ... – siffiejoe

2

Tôi đã nhìn thấy thông báo này trong một tình huống tương tự; trong trường hợp của tôi, nó liên quan đến thiết kế của ngx_lua, thực hiện bộ lập lịch trình coroutine của riêng nó. Điều này có nghĩa là sock:receive không chặn, nhưng thay vào đó sẽ ẩn yield thành trình lên lịch và kết quả là, nếu cuộc gọi đến sock:receive được thực hiện với chức năng C đang ở trên ngăn xếp, bạn có thể gặp lỗi bạn thấy.

Trong trường hợp của tôi, tôi đã thực hiện cuộc gọi từ một móc gỡ lỗi và đã nhận được lỗi này cho đến khi tôi chuyển sang sử dụng các phương pháp socket từ phiên bản luasocket của chính tôi không mang lại lợi nhuận. Tôi muốn kiểm tra xem socket.smtp có đang sử dụng phiên bản luasocket "bình thường" không.

4

Điều này là do việc sử dụng kết hợp LuaJIT và socket.smtp, tạo thành một coroutine. Từ 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.

Dường như cách giải quyết tốt nhất có thể được sử dụng thực hiện này của require.lua: https://github.com/pygy/require.lua. Nó được viết bằng Lua thuần túy, thay vì C, để giải quyết vấn đề này với LuaJIT.

+0

Hmm, tôi đã tải xuống 'require-lua 0.1.7-2' và cài đặt thông qua luarocks, sau đó đặt' require = require "yêu cầu" .require' ở đầu tập lệnh của tôi. Tôi vẫn nhận được cùng một lỗi: 'cố gắng sinh lợi qua ranh giới C-call' từ hàm smtp.send. – arby

+0

arby, có vẻ như câu trả lời của @ siffiejoe ở đây là câu trả lời đúng. Nếu socket.protect được viết bằng C, thì đó là vấn đề cơ bản thực sự! –

Các vấn đề liên quan