2

我想在 luajit 中捕获 SIGINT。最终我希望能够捕获 SIGUSR1。目的是允许我编写 logrotate 兼容日志记录,在收到 SIGUSR1 后,日志文件关闭然后重新打开。

我怎样才能使用 FFI?

这是我到目前为止所拥有的。

local ffi = require("ffi")
local C = ffi.C

local SIG_ERR = -1
local SIGINT  = 1
local SIGUSR1 = 10


ffi.cdef[[
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
]]


local function handler(signo)
   print("caught sig\n")
end

if C.signal(SIGINT, handler) == SIG_ERR then
  print("Can't catch SIGINT\n")
end

while 1 do
end

实际上,我认为这里发生了一些事情。我注意到您必须按 ctrl+c 两次,然后程序退出。并且两次都没有调用“caught sig”。我认为 lua 解释器的 C 端已经在捕获 SIGINT 了。

所以我决定将 SIGINT 更改为 SIGUSR1,因为这最终是我需要的。我注意到它触发了捕获,但我得到了

"PANIC: unprotected error in call to Lua API (bad callback)"

听起来我的回调函数的格式有问题,但我不确定如何纠正。Lua 对我来说还是很新鲜的东西。

4

1 回答 1

8

如果VM 已经在运行代码,从信号处理程序调用 LuaJIT VM 是不安全的Lua 代码是解释还是编译都没有关系。信号处理程序是异步调用的,VM 可能处于不一致的状态。

可以创建第二个 VM ( ffi.C.luaL_newstate()),为该 VM 中的函数设置信号处理程序,然后以某种方式在两个 VM 之间进行通信。但这非常复杂,很难做到正确。

我想它会更容易使用sigpending()(定期检查,例如在日志函数中)或signalfd()(如果你已经有一个事件处理循环)。

于 2013-10-17T16:36:10.507 回答