diff options
-rw-r--r-- | net/server_epoll.lua | 3 | ||||
-rw-r--r-- | util-src/signal.c | 69 |
2 files changed, 63 insertions, 9 deletions
diff --git a/net/server_epoll.lua b/net/server_epoll.lua index a064dcfa..127d049e 100644 --- a/net/server_epoll.lua +++ b/net/server_epoll.lua @@ -1147,12 +1147,13 @@ end local hook_signal; if have_signal and signal.signalfd then local function dispatch(self) - return self:on("signal", signal.signalfd_read(self:getfd())); + return self:on("signal", self.conn:read()); end function hook_signal(signum, cb) local watch = watchfd(signal.signalfd(signum), dispatch); watch.listeners = { onsignal = cb }; + watch.close = nil; -- revert to default return watch; end end diff --git a/util-src/signal.c b/util-src/signal.c index 3af80a73..ef35067b 100644 --- a/util-src/signal.c +++ b/util-src/signal.c @@ -373,29 +373,66 @@ static int l_kill(lua_State *L) { #endif #ifdef __linux__ -static int l_signalfd(lua_State *L) { +struct lsignalfd { + int fd; sigset_t mask; +}; + +static int l_signalfd(lua_State *L) { + struct lsignalfd *sfd = lua_newuserdata(L, sizeof(struct lsignalfd)); - sigemptyset(&mask); - sigaddset(&mask, luaL_checkinteger(L, 1)); + sigemptyset(&sfd->mask); + sigaddset(&sfd->mask, luaL_checkinteger(L, 1)); - sigprocmask(SIG_BLOCK, &mask, NULL); /* TODO check err */ + sigprocmask(SIG_BLOCK, &sfd->mask, NULL); /* TODO check err */ - lua_pushinteger(L, signalfd(-1, &mask, SFD_NONBLOCK)); + sfd->fd = signalfd(-1, &sfd->mask, SFD_NONBLOCK); + + if(sfd->fd == -1) { + lua_pushnil(L); + return 1; + } + + luaL_setmetatable(L, "signalfd"); + return 1; +} + +static int l_signalfd_getfd(lua_State *L) { + struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd"); + + if (sfd->fd == -1) { + lua_pushnil(L); + return 1; + } + + lua_pushinteger(L, sfd->fd); return 1; } static int l_signalfd_read(lua_State *L) { - const int sigfd = luaL_checkinteger(L, 1); + struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd"); struct signalfd_siginfo siginfo; - if(read(sigfd, &siginfo, sizeof(siginfo)) < 0) { + if(read(sfd->fd, &siginfo, sizeof(siginfo)) < 0) { return 0; } lua_pushinteger(L, siginfo.ssi_signo); return 1; } + +static int l_signalfd_close(lua_State *L) { + struct lsignalfd *sfd = luaL_checkudata(L, 1, "signalfd"); + + if(close(sfd->fd) != 0) { + lua_pushboolean(L, 0); + return 1; + } + + sfd->fd = -1; + lua_pushboolean(L, 1); + return 1; +} #endif static const struct luaL_Reg lsignal_lib[] = { @@ -406,7 +443,6 @@ static const struct luaL_Reg lsignal_lib[] = { #endif #ifdef __linux__ {"signalfd", l_signalfd}, - {"signalfd_read", l_signalfd_read}, #endif {NULL, NULL} }; @@ -415,6 +451,23 @@ int luaopen_prosody_util_signal(lua_State *L) { luaL_checkversion(L); int i = 0; +#ifdef __linux__ + luaL_newmetatable(L, "signalfd"); + lua_pushcfunction(L, l_signalfd_close); + lua_setfield(L, -2, "__gc"); + lua_createtable(L, 0, 1); + { + lua_pushcfunction(L, l_signalfd_getfd); + lua_setfield(L, -2, "getfd"); + lua_pushcfunction(L, l_signalfd_read); + lua_setfield(L, -2, "read"); + lua_pushcfunction(L, l_signalfd_close); + lua_setfield(L, -2, "close"); + } + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +#endif + /* add the library */ lua_newtable(L); luaL_setfuncs(L, lsignal_lib, 0); |