在Linux下,如何在LuaJIT中捕获SIGUSR1信号?

我想在 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 对我来说仍然是很新的东西。

点赞
用户1657919
用户1657919

如果 LuaJIT VM 正在主动运行代码,从信号处理程序调用 LuaJIT VM 不是 安全的。无论 Lua 代码是解释性还是编译性都无所谓。信号处理程序是异步调用的,VM 可能不处于一致的状态。

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

我想使用 sigpending()(例如在日志函数中定期检查)或 signalfd()(如果您已经有事件处理循环)可能更容易些。

2013-10-17 16:36:10